I have an input file (exert from file shown below) with multiple lines that I need to select specific text from and put each selection into an array element:
exert from input file:
"BLOCK","PARTNO"
"ELEMENT","HEADER-"
"NAME","1AB000072186"
"REVISION","0000"
"PARTSHAPE","RECT_074_044_030"
"PACKAGE","120830E"
"PMABAR",""
"PARTCOMMENT","CAP-TANT*150uF*20%*10V7343*4.3mm"
"ELEMENT","PRTIDDT-"
"PMAPP",1
"PMADC",2
"ComponentQty",2
"BLOCK","PARTNO"
"ELEMENT","HEADER-"
"NAME","1AB030430005"
"REVISION","0000"
"PARTSHAPE","RECT_072_042_030"
"PACKAGE","120830E"
"PMABAR",""
"PARTCOMMENT","1.0000 Amp SUBMINIATURE FUSE"
"ELEMENT","PRTIDDT-"
"PMAPP",2
"PMADC",0
"ComponentQty",1
"BLOCK","PARTNO"
"ELEMENT","HEADER-"
"NAME","1AB030430001"
"REVISION","0000"
"PARTSHAPE","RECT_072_042_030"
"PACKAGE","120830E"
"PMABAR",""
"PARTCOMMENT","2.0000 Amp SUBMINIATURE FUSE"
"ELEMENT","PRTIDDT-"
"PMAPP",2
"PMADC",0
"ComponentQty",1
Notice that after each occurrence of the line with the phrase "ComponentQty" the content begins repeating...
Where I need the PartNumber that is next to the occurrence of "NAME" in one dimension of the array element and the content next to the occurrence of "PARTSHAPE" in the second dimension for each element. I am very confused on how to do this though...please help!!!
$fh = fopen('yourfile.txt', 'rb');
$found_stuff = array();
$last_component = null;
while($line = fgets($fh)) { // read a line
$parts = explode(',', $line); // split into components
switch($parts[0]) { // based on which key we're on
case '"NAME"':
$last_component = $parts[1]; // save the key's value
break;
case '"PARTSHAPE"':
$found_stuff[$last_component] = $parts[1]; // store the partshape name
break;
}
}
fclose($fh);
This should do the basic work. Read a line, explode it into pieces where commas occur. The first part will be the "key", the second part will be the value. Then simply keep reading until we either hit a NAME or a PARTSHAPE key, then store the values as appropriate.
Note that I've not stripped the double-quotes off the values. That's left as an exercise to the reader. This code also assumes that the file's format is regular and that a "NAME" will show up before any PARTSHAPE lines, and there'll be a perfect 1:1 alternation between NAME/PARTSHAPE lines. If you get two PARTSHAPES in a row, you'll lose the first one. And if a PARTSHAPE shows up before the first NAME is encounted, you'll sorta lose that one too.
The following steps worked for me:
The section pasted in my OP (repeating many times more) is defined as $PartNoContents
and $BlockData[] is the array that I need to paste selections from $PartNoContents into.
$PartNoContents = str_replace('"', '', $PartNoContents);
$PartLines = explode("\n", $PartNoContents);
$PartData = array();
foreach ($PartLines as $PartLine){
$PartData[] = explode(',', $PartLine);
}
for($p=0;$p<count($PartLines);$p++){
if ( isset( $PartData[$p][1] ) && !empty( $PartData[$p][1] ) ){
$p1 = str_replace(chr(13), '', $PartData[$p][1]);
if ( isset($BlockData[$b][0]) && !empty($BlockData[$b][0]) && $BlockData[$b][7]==$p1 ){
$BlockData[$b][13] = str_replace(chr(13), '', $PartData[$p+$PartDataIncNum][1]);
$p = count($PartLines) ;
}
}
}
Related
I'm using a function to output a collection of products in Shopify, onto a WordPress page.
I've got most of the data displaying correctly, except a custom value that is entered as a tag in Shopify. Using the api, I'm then trying to get this specific tag for the product subtitle which is formatted with att:Subtitle: before each product custom value/text.
This is the code I have got to (I've commented other unsuccessful attempts in the middle) - this is inside the overall code to show the 4 products in the Shopify collection:
// Using tags to output custom data from products
$tags = $current_product['tags'];
// $tags is a string, this turns the values into an array
$product_tags = explode(',', $tags);
// Evaluate if there is a string with att:Subtitle in the product tags
// https://tecadmin.net/check-string-contains-substring-in-php/
$subtitle_attribute_key = "att:Subtitle:";
if (strpos($tags, 'att:Subtitle:') !== false) {
// Returns a numbered value corresponding to my subtitle attribute
// $key = array_search($subtitle_attribute_key, $product_tags);
$sub = strpos($tags, $subtitle_attribute_key);
// Turns the numbered value into a text value
// $numArray = explode(" ", $sub);
// var_dump($numArray);
$value = print_r($sub, true);
// $value = array_search("att:Subtitle:",$product_tabs);
// $value = array_search("att:Subtitle:", $tabs); // Warning: array_search() expects parameter 2 to be array, null given
// $result = $product_tags['$value']; // my attempt to return the text
// Remove att:Subtittle: in front of the subtitle value to output the clean final value
$subtitle = ltrim($value, 'att:Subtitle:');
}
So far it comes out as a number value where I'm displaying $subtitle... but I can't figure out how to display the custom text value instead.
Any ideas?
Thanks
EDIT: I am working with products that have multiple tags and I do not control these. Out of the tags I'm trying to find the one that starts with att:Subtitle: but only show the custom value after that marker.
When I echo $tags, the ist comes out something like this:
att:Benefit:balance, att:Perfect:Combination Skin, att:Size: 1.8 oz, att:Subtitle: Multi-Tasking Product, Key Ingredient 1, Key Ingredient 2, Essentials, meta-related-product-xyz, meta-related-product-brandname
They will all have a different list of tags
Of course it comes out as a number. You're getting a number from the strpos() and ultimate trying to run ltrim() on it.
If you're expecting the desired text to be in $tags immediately following 'att:Subtitle:' and have nothing else in that string, $subtitle = substr($tags, strpos('att:Subtitle:') + strlen('att:Subtitle:')); should give it to you. If you're expecting it to possibly be an element in the $product_tags array, need to loop (I'm assuming it shows up once, at most):
foreach ($product_tags as $product_tag) {
if (strpos($product_tag, 'att:Subtitle:') !== false) {
$subtitle = substr($product_tag, strpos($product_tag, 'att:Subtitle:') + strlen('att:Subtitle:'));
break;
}
}
So for what I understand you're trying to get rid of 'att:Subtitle:' from the tags on your products descriptions? maybe you should try replacing that value on your tags array
// Using tags to output custom data from products
$tags = $current_product['tags'];
// $tags is a string, this turns the values into an array
$product_tags = explode(',', $tags);
// Get rid of attribute on product tag
for($i = 0; $i < count($product_tags); $i++){
$subtitle = str_replace(':att:Subtitle','',$product_tags[i]);
}
I have four files named comma separated in one field in database like this file1,file2,file3,file4. It may change depending on files uploading. User can upload maximum 4 files, minimum one file. But I was not able to get it. I used explode but it's taking too long.
I am using this code:
$imagefiles = $row["imagefiles"];
$cutjobs = explode(",", $imagefiles);
$cutjobs1 = count($cutjobs);
$image1 = $cutjobs[0];
$image2 = $cutjobs[1];
$image3 = $cutjobs[2];
$image4 = $cutjobs[3];
if (empty($image1)) {
$imagefiles1 = "";
} else {
$imagefiles1 = 'http://projects.santabantathegreat.com/glassicam/uploads/'.$registerid.
"/".$viewjobsid.
"/".$image1;
}
if (empty($image2)) {
$imagefiles2 = "";
} else {
$imagefiles2 = 'http://projects.santabantathegreat.com/glassicam/uploads/'.$registerid.
"/".$viewjobsid.
"/".$image2;
}
if (empty($image3)) {
$imagefiles3 = "";
} else {
$imagefiles3 = 'http://projects.santabantathegreat.com/glassicam/uploads/'.$registerid.
"/".$viewjobsid.
"/".$image3;
}
if (empty($image4)) {
$imagefiles4 = "";
} else {
$imagefiles4 = 'http://projects.santabantathegreat.com/glassicam/uploads/'.$registerid.
"/".$viewjobsid.
"/".$image4;
}
}
$data[] = array( 'imagearray' => array($imagefiles, $imagefiles1, $imagefiles2, $imagefiles3));
}
echo json_encode($data);
}
I am getting output like this :
[{"imagearray":["http:\/\/projects.santabantathegreat.com\/glassicam\/uploads\/60\/30\/file1.jpg","http:\/\/projects.santabantathegreat.com\/glassicam\/uploads\/60\/30\/file2.jpg",""]}]
If you see this imageArray last one is getting "" that means some in file1, file2, file3, file4 one name is missing so I want to show if any filename is not there means I don't want to show null values with ""
i have a field with file1,file2,file3,file4 so times we will have file1,file3 then remaining will not there so i want to count file name separated with commas and if file1 is there is should print that if file3 is there not then it shouldn't show with ""
You could have used split(), but its deprecated in PHP 5.3.0. So, instead you are left with:
explode() which is substantially faster because it doesn't split based on a regular expression, so the string doesn't have to be analyzed by the regex parser.
or
preg_split() which is faster and uses PCRE regular expressions for regex splits.
With preg_split() you could do:
<?php
$encoded_data = json_encode($data);
$images = preg_split('/,/', $encoded_data->imagearray);
?>
I would say that explode() is more appropriate for this.
<?php
$encoded_data = json_encode($data);
$images = explode(',', $encoded_data->imagearray);
print_r($images);
?>
Resources: What is the difference between split() and explode()?
You shouldn't have empty values in your array in the first place. But if you still have any empty values you could use preg_split() something like this one here.
Similarly you can use array_filter() to handle removal of values (null, false,'',0):
print_r(array_filter($images));
There are so many answers here in this forum that do exactly what you are asking: Remove empty array elements, Delete empty value element in array.
I'm not sure exactly how to phrase this so I will show an example. I'm gathering input values in javascript and passing to my php page where I am trying to insert those values in a database.
Instead of inserting separate values it is inserting the entire string.
Part of my javascript below:
var form = document.forms[0];
var txtS = form["bulletlabels"];
var len = txtS.length;
var bulletlabels = "";
for(i=0;i<len;i++) {
bulletlabels += '"'+[i]+'_'+(txtS[i].value)+'_label",';
}
when I do an alert(bulletlabels); I get this:
"0_Lot Size_label","1_Rooms_label","2_Bathrooms_label","3_Basement_label",
On my php page I have:
$bulletlabels = array($_POST['bulletlabels']);
$length = count($bulletlabels);
for ($i = 0; $i < $length; $i++) {
mysqli_query($con,"UPDATE bullets SET bullettitle = '".$bulletlabels[$i]."' WHERE bulletrow = ($i+1)");
}
This inserts the below string into the database on ONE Row which is not the desired effect:
"0_Lot Size_label","1_Rooms_label","2_Bathrooms_label","3_Basement_label",
But here is the key to my confusion - if I manually type the string in, it inserts onto individual database rows as desired.
This inserts values individually as desired when typed manually:
$bulletlabels = array("0_Lot Size_label","1_Rooms_label","2_Bathrooms_label","3_Basement_label",);
Does NOT work and inserts the full concatenated string:
$bulletlabels = array($_POST['bulletlabels']);
Hope I explained well enough - arrays elude me.
EDIT:
Fix for the trailing comma:
var delim = "";
for(i=0;i<len;i++) {
bulletlabels += delim+[i]+'_'+(txtS[i].value)+'_label';
delim = ",";
}
Reference link for trailing comma fix:
Can you use a trailing comma in a JSON object?
Try changing the following line:
$bulletlabels = array($_POST['bulletlabels']);
to
$bulletlabels = explode(',', $_POST['bulletlabels']);
Also do not add quotes in your javascript:
bulletlabels += '"'+[i]+'_'+(txtS[i].value)+'_label",';
should be
bulletlabels += [i]+'_'+(txtS[i].value)+'_label,';
Explanation:
Currently, $bulletlabels is an array with one element, and this element is the following string: "0_Lot Size_label","1_Rooms_label","2_Bathrooms_label","3_Basement_label",. However, you want to have an array with several strings. That's why you need to use the explode function to convert it into a proper array.
Note:
Make sure not to include , in the label names, as it will break with this implementation. If you need to be able to use , too, you should use json functions.
I am trying to format another sites data to insert into my database. He wants to close his site, so is giving me his sites listings. But im having to format his data from his flatfile database, to go into my mysql database.
Im looping through his text file, and getting his values. Then formatting as needed before inserting them into my DB.
Because our sites use completely different storage formats and fields, im having a few problems with something.
My site has a designer field. His doesnt. so im trying to search through his description field to find a match within my designer table. If there is a match i want to get the designer ID to insert into the designer id field. But i cant get this code to work.
Could someone please suggest a fix? or if theres a better way to do this?
$fp = fopen('listings.txt','r');
if (!$fp) {echo 'ERROR: Unable to open file.'; exit;}
$loop = 0;
while (!feof($fp)) {
$loop++;
$line = fgets($fp,1024); //use 2048 if very long lines
$field[$loop] = explode (' ', $line);
$get_designers = mysql_query("SELECT * FROM dress_designers");
$row_designers = mysql_fetch_array($get_designers);
$totalRows_designers = mysql_num_rows($get_designers);
do{
// Note our use of ===. Simply == would not work as expected
// because the position of 'a' was the 0th (first) character.
$mystring = strtolower($field[$loop][8]);
$findme = strtolower($row_designers['designer_name']);
$pos = strpos($mystring, $findme);
// Note our use of ===. Simply == would not work as expected
// because the position of 'a' was the 0th (first) character.
if ($pos === false) {
$designer = "Other";
} else {
$designer = "Siopa Rince";
}
} while ($row_designers = mysql_fetch_assoc($get_designers));
$fp++;
}
fclose($fp);
I only put "Siopa Rince" as a test. But this isnt working. If i take the text from the file, and paste it in the $mystring and put siopa rince in $findme... it works.
Any suggestions would be greatly appreciated!
Thanks,
Danny
OK... what about just entering the info as is? I tried a few different ways, but the result is returning null...
After i insert the data, ill use searches to join the required row to get an ID:
SELECT dress_test.dress_title, (
SELECT dress_designers.designer_id
FROM dress_designers
WHERE MATCH (
dress_test.dress_desc
)
AGAINST (
'dress_designers.designer_name'
IN boolean MODE
)
) AS real_designer_id
FROM dress_test
Another version:
SELECT dress_test.dress_title, dress_designers.designer_name
FROM dress_test
JOIN dress_designers ON MATCH(dress_test.dress_title, dress_test.dress_desc) AGAINST
('dress_designers.designer_name' in boolean mode)
Any other suggestions??
Your first assignment to $row_designers uses mysql_fetch_array, while your second uses mysql_fetch_assoc
Instead of do { ... } while, why not just while () { ... }
Remove this line $row_designers = mysql_fetch_array($get_designers);
And turn your loop into...
while ($row_designers = mysql_fetch_assoc($get_designers)) {
// string search here
}
Everything else looks fine - if you're having troubles, check the values with either echo to print string or print_r to print arrays.
I have a text file with something like
Country1
city1
city2
Country2
city3
city4
I want to separate country and cities. Is there any quick way of doing it? I am thinking of some file handling and then extracting to different files, is it best way or can be done with some regex etc quickly?
countries=[]
cities=[]
with open("countries.txt") as f:
gap=True
for line in f:
line=line.strip()
if gap:
countries.append(line)
gap=False
elif line=="":
gap=True
else:
cities.append(line)
print countries
print cities
output:
['Country1', 'Country2']
['city1', 'city2', 'city3', 'city4']
if you want to write these to files:
with open("countries.txt","w") as country_file, open("cities.txt","w") as city_file:
country_file.write("\n".join(countries))
city_file.write("\n".join(cities))
f = open('b.txt', 'r')
status = True
country = []
city = []
for line in f:
line = line.strip('\n').strip()
if line:
if status:
country.append(line)
status = False
else:
city.append(line)
else:
status = True
print country
print city
output :
>>['city1', 'city2', 'city3', 'city4']
>>['Country1', 'Country2']
$countries = array();
$cities = array();
$gap = false;
$file = file('path/to/file');
foreach($file as $line)
{
if($line == '') $gap = true;
elseif ($line != '' and $gap)
{
$countries[] = $line;
$gap = false;
}
elseif ($line != '' and !$gap) $cities[] = $line;
}
Depending on how regular your file is, it may be this simple in python:
with open('inputfile.txt') as fh:
# To iterate over the entire file.
for country in fh:
cityLines = [next(fh) for _i in range(2)]
# read a blank line to advance countries.
next(fh)
That's not likely to be exactly right, because I imagine many countries have variable numbers of cities. You could modify it like so to address that:
with open('inputfile.txt') as fh:
# To iterate over the entire file.
for country in fh:
# we assume here that each country has at least 1 city.
cities = [next(fh).strip()]
while cities[-1]: # will continue until we encounter a blank line.
cities.append(next(fh).strip())
That doesn't do anything to put the data into an output file, or store it much past the file handle itself, but it's a start. You really should choose a language for your questions though. A lot of the time until
Another PHP example that doesn't read the entire file in an array.
<?php
$fh = fopen('countries.txt', 'r');
$countries = array();
$cities = array();
while ( $data = fgets($fh) )
{
// If $country is empty (or not defined), the this line is a country.
if ( ! isset($country) )
{
$country = trim($data);
$countries[] = $country;
}
// If an empty line is found, unset $country.
elseif ( ! trim($data) )
unset($country);
// City
else
$cities[$country][] = trim($data);
}
fclose($fh);
The $countries array will contain a list of countries while the $cities array will contain a list of cities by countries.
Is there some pattern that distinguishes countries from cities? Or is it that the first line after a blank line is a country and all subsequent lines are city names until the next blank line? Alternatively are you finding countries based on a look-up table (a "dictionary" in Python; an associative array in PHP; a hash in Perl --- one that includes all the officially recognized countries)?
Is it safe to assume that there are no cities whose names collide with any country? Is there a France, Iowa, USA, or the old Usa, Japan?
What do you want to do with these after you separate them? You mention "some file handling and then extracting to different files" --- are you thinking of something like one file per country containing a list of all the cities therein? Or one directory per country and one file per city?
The obvious approach would be to iterate over the file, line by line, and maintain a little state machine: empty (beginning of file, blank lines between countries?) during which you enter the "country" state (whenever you found any pattern that matches whatever criteria means you've encountered the name of a country). Once you've found a country name then you're in the city loading state. I would create a dictionary using country names as keys and set of cities as cities (though perhaps you might really need county/provice, city name tuples in cases where a country has multiple cities by the same name: Portland, Maine vs. Portland, Oregon, for example). You can also have some "error" state if the contents of your file lead to some sort of ambiguity (city names before you've determined a country, two country names in a row, whatever).
It's hard to suggest a good fragment of code given how vague your spec. here is.
Not sure that this would help, but you can try to use the following code to get dictionary and then work with it(write to files, compare and etc):
res = {}
with open('c:\\tst.txt') as f:
lines = f.readlines()
for i,line in enumerate(lines):
line = line.strip()
if (i == 0 and line):
key = line
res[key] = []
elif not line and i+1 < len(lines):
key = lines[i+1].strip()
res[key] = []
elif line and line != key:
res[key].append(line)
print res
This regex would work for your example:
/(?:^|\r\r)(.+?)\r(.+?)(?=\r\r|$)/s
Catches countries in group 1 and cities in group 2.
You may have to adjust your newline characters, depending on your system. They can be \n, \r or \r\n. edit: added a $ sign, so you don't need two linebreaks at the end. You will need the flag for dotall for the regex to work as expected.
Print fild 1 with awk - countries
awk 'BEGIN {RS="";FS="\n"} {print $1 > "countries"} {for (i=2;i<=NF;i++) print $i > "cities"}' source.txt