Export a text file to MySQL in Talend - mysql

So I have many files like this :
The first file :
File1;
Code;1971;1981;1991;2001;2011
A;10;20;30;40;50
B;12;22;32;89;95
...
...
The second file :
File2;
Code;1971;1981;1991;2001;2011
A;1500;1600;460;6000;8000
B;6000;7000;8007;8009;9005
...
...
All Files have the exact same format.
I like to have a table in my database like this :
File Code Year Value
File1 A 1971 10
File1 A 1981 20
File1 A 1991 30
. . .
. . .
File2 A 1971 1500
File2 A 1981 1600
File1 A 1991 460
. . . .
. . . .
File2 B 1971 .
File2 B 1981 .
. . . .
My idea is to creat for each file a t_map in wich we have the file as follow :
My solution with t_map
The problem is that I have so many file like this, and my solution will take me a long time to finish it. Is there any better solution ?

I prefer using PHP to dump all data into MySQL...
Code;1971;1981;1991;2001;2011
A;10;20;30;40;50
B;12;22;32;89;95
after Open & Read file ($file), try this...
<?php
function _T($a){return rtrim(trim($a));}
function _E($a,$b){return explode($a,$b);}
function _S($a,$b,$c){return str_replace($a,$b,$c);}
function _G($a,$b,$c){$d=strpos($a,$b);$e=substr($a,$d);$f=strpos($a,$c);return substr($e,0,($f-$d));}
$file='Code;1971;1981;1991;2001;2011
A;10;20;30;40;50
B;12;22;32;89;95';
$fC=_E('|',_S('Code;','|Code;',$file));
/*Useful with Multiple "Code;" in same file too*/
$fC2=($file).'|';
/* Add "|" to the last */
$fY=array();/*Year*/
$fA=array();/*A*/
$fB=array();/*B*/
$dB=array();/* For Database */
foreach($fC as $fR){
/* Get Year; */
$gY=_E(';',_S('Code;','',_G(_T($fR),'Code;','A;')));
$c=0;foreach($gY as $yR){if(!empty($yR)){/*echo _T($yR).'<br>';*/$fY[$c++]=_T($yR);}}
/* Get A */
$gA=_E(';',_S('A;','',_G(_T($fR),'A;','B;')));
$c=0;foreach($gA as $aR){if(!empty($aR)){/*echo _T($aR).'<br>';*/$fA[$c++]=_T($aR);}}
/* Get B */
$gB=_E(';',_S('B;','',_G(_T($fR),'B;','|')));
$c=0;foreach($gB as $bR){if(!empty($bR)){/*echo _T($bR).'<br>';*/$fB[$c++]=_T($bR);}}
if(empty($fB)){$gB=_E(';',_S('B;','',_G(_T($fC2),'B;','|')));
$c=0;foreach($gB as $bR){if(!empty($bR)){/*echo _T($bR).'<br>';*/$fB[$c++]=_T($bR);}}}
}
/* Show Result */
foreach($fY as $fK=>$fV){
echo $fK.':'.$fV.'='.$fA[$fK].'='.$fB[$fK].'<br>';
$dB[]=array('Year'=>$fV,'A'=>$fA[$fK],'B'=>$fB[$fK]);
}print_r($dB);
?>
Test yourself... :)

Related

awk: appending columns from multiple csv files into a single csv file

I have several CSV files (all have the same number of rows and columns). Each file follows this format:
1 100.23 1 102.03 1 87.65
2 300.56 2 131.43 2 291.32
. . . . . .
. . . . . .
200 213.21 200 121.81 200 500.21
I need to extract columns 2, 4 and 6, and add them to a single CSV file.
I have a loop in my shell script which goes through all the CSV files, extracts the columns, and appends these columns to a single file:
#output header column
awk -F"," 'BEGIN {OFS=","}{ print $1; }' "$input" > $output
for f in "$1"*.csv;
do
if [[ -f "$f" ]] #removes symlinks (only executes on files with .csv extension)
then
fname=$(basename $f)
arr+=("$fname") #array to store filenames
paste -d',' $output <(awk -F',' '{ print $2","$4","$6; }' "$f") > temp.csv
mv temp.csv "$output"
fi
done
Running this produces this output:
1 100.23 102.03 87.65 219.42 451.45 903.1 ... 542.12 321.56 209.2
2 300.56 131.43 291.32 89.57 897.21 234.52 125.21 902.25 254.12
. . . . . . . . . .
. . . . . . . . . .
200 213.23 121.81 500.21 231.56 5023.1 451.09 ... 121.09 234.45 709.1
My desired output is a single CSV file that looks something like this:
1.csv 1.csv 1.csv 2.csv 2.csv 2.csv ... 700.csv 700.csv 700.csv
1 100.23 102.03 87.65 219.42 451.45 903.1 542.12 321.56 209.2
2 300.56 131.43 291.32 89.57 897.21 234.52 125.21 902.25 254.12
. . . . . . . . . .
. . . . . . . . . .
200 213.23 121.81 500.21 231.56 5023.1 451.09 ... 121.09 234.45 709.1
In other words, I need a header row containing the file names in order to identify which files the columns were extracted from. I can't seem to wrap my head around how to do this.
What is the easiest way to achieve this (preferably using awk)?
I was thinking of storing the file names into an array, inserting a header row and then print the array but I can't figure out the syntax.
So, based on a few assumptions:
the inputs are called "*.csv" but they're actually whitespace-separated, as they appear.
the odd-numbered input columns just repeat the row number 3 times, and can be ignored
the column headings are just the filenames, repeated 3 times each
they are input to some other program, and the numbers are left-justified anyway, so you aren't particular about the column formatting (columns lining up, decimals aligned, ...)
Humble apologies because code PRE formatting is not working for me here
f=$(set -- *.csv; echo $*)
(echo $f; paste $f) |
awk 'NR==1 { for (i=1; i<=NF; i++) {x=x" "$i" "$i" "$i} }
NR > 1 { x=$1; for (i=2; i<= NF; i+=2) {x=x" "$i} }
{print x}'
hth

How can I enter similar lines of code with sublime text with just one char different?

I have to write code which is like
apple1 =1
banana1 =10
cat1 =100
dog1 =1000
apple2 =2
banana2 =20
cat2 =200
dog2 =2000
.
.
.
<to be done till>
apple50 =50
banana50 =500
cat50 =5000
dog50 =50000
Is there any shortcut to copy paste the first 4 line and keep pasting with running sequence ?
Any level of short cut is appreciated to do this partially or completely.
Thanks
As already mentioned the easiest way to do it is using a programming language, but you can use python in Sublime Text.
Open the ST console ctrl+` and paste:
view.run_command("insert", {"characters": "\n\n".join("apple{0} ={0}\nbanana{0} ={0}0\ncat{0} ={0}00\ndog{0} ={0}000".format(i) for i in range(1, 51))})
this will insert the requested content.
You could also write a plugin using Tools >> New Plugin... and paste:
import sublime
import sublime_plugin
class PasteSequenceCommand(sublime_plugin.TextCommand):
def run(self, edit):
view = self.view
content = sublime.get_clipboard()
content, sequence_number = content.replace("1", "{0}"), 2
if content == view.settings().get("ps_content"):
sequence_number = view.settings().get("ps_sequence_number") + 1
view.settings().set("ps_content", content)
view.settings().set("ps_sequence_number", sequence_number)
view.run_command("insert", {"characters": content.format(sequence_number)})
Afterwards add keybinding:
{
"keys": ["ctrl+shift+v"],
"command": "paste_sequence"
},
Then you can copy the block containing the 1 and each 1 will increase each time you use the paste sequence command.
For me it seems that this task is not for text editor. It looks more like task for a script. For example in bash it would be like following:
#!/bin/bash
for i in `seq 1 50`;
do
echo "apple$i .. ${i}=${i}" >> text.txt
echo "banana$i =${i}0" >> text.txt
echo "cat$i =${i}00" >> text.txt
echo "dog$i =${i}000" >> text.txt
done
To run it:
create file, say inserter.sh
make it executable by chmod +x inserter.sh
run it ./inserter.sh
Result will be in text.txt file in the same folder.
You need to redirect the output to a file.
#!/bin/bash
cntr=1
banana_cntr=10
cat_cntr=100
dog_cntr=1000
for i in `seq 1 1 50`
do
echo "apple${cntr}=$[$cntr * 1]"
echo "banana${cntr}=`expr $cntr \* $banana_cntr`"
echo "cat${cntr}=`expr $cntr \* $cat_cntr`"
echo "dog${cntr}=`expr $cntr \* $dog_cntr`"
cntr="$[cntr + 1]"
echo " "
done

Export the result of MySQL query to my PC as a CSV file

I would like to export some MySQL-query results to my PC as a CSV-file. According to some contributions in the internet (e.g. here) it should work like the following:
mysql> SELECT 1,2,3,4,5 INTO OUTFILE 'C:\Users\MyPC\Desktop\numbers.csv';
ERROR 1 (HY000): Can't create/write to file 'C:\Users\MyPC\Desktop\numbers.csv' (Errorcode: 22 Invalid argument)
But theat leads to the given error. Waht am I doing wrong here? How can I save the output of my query as a csv ot a txt file?
P.S.: Im am using Windows
First of all, you didn't mention FROM which database you want the entrys.
SELECT 1,2,3,4,5 FROM ??????????????? INTO ...
With PHP you can do it like this:
$dz=fopen("file.csv", "w+");
$sql = "SELECT 1,2,3,4,5 FROM ?????????";
if ($result = $connectiontodatabase->query($sql)) {
while ($row = $result->fetch_assoc()) {
fputs($dz, $row['1'] . "\t" . $row['2'] . "\t" . $row['3' . "\t" . $row['4'] . "\t" . $row['5'] . "\t\n");
}}
fclose($dz);
$connectiontodatabase of course needs to be the new mysqli statement

Exim script before queue

I need to open exim relay to a list of ips in a mysql database.
I think if I can run a script before a email is queued, I can do that. Is there a way?
Mail Enable for windows has a similar solution called "SMTP Inbound Command Scripting".
# configure
. . . . .
hide mysql_servers = localhost/myoneandonlybase/login/pass
hostlist myfriends = ${lookup mysql{SELECT ipaddr FROM submitters}}
. . . . .
acl_smtp_connect = acl_conn
acl_smtp_rcpt = acl_rcpt
acl_smtp_data = acl_data
. . . . .
begin acl
acl_conn:
accept hosts = +myfriends
. . . . .
acl_rcpt:
accept hosts = +myfriends
. . . . .
acl_data:
accept hosts = +myfriends
. . . . .
The default exim configuration file already has a hostlist relay_from_hosts that you can easily populate with an SQL lookup and get the desired result:
hide mysql_servers = localhost/myoneandonlybase/login/pass
hostlist relay_to_domains = ${lookup mysql{SELECT ipaddr FROM submitters}}
Nothing more than that is needed.

RegEx match for multiline in Perl

I have following data line i need to parse in Perl:
my $string='Upper Left ( 440720.000, 3751320.000) (117d38\'28.21"W, 33d54\'8.47"N)';
Here is my perl script:
if ($string=~ m/Upper Left\s+[(]\s+\d{1,6}[.]\d{1,3}[\,]\s+\d{1,6}[.]\d{1,3}[)]\s+[(](\d{1,3})d(\d{1,2})['](\d{1,2})[.](\d{1,2})/ig) {
$upperLeft="lat=". $1. 'd'. $2. "'". $3. ".". $4. '"W long='. $5. 'd'. $6. "'". $7. ".". $8. '"W';
print $upperLeft. "\n";
}
However this expression fails to 117d38'28.21" as lat and 33d54'8.47 as long. Note the space and '(' in the input $string which i use to create this regular expression.
What I am I doing wrong in extracting (117d38'28.21"W, 33d54'8.47"N) into 8 fields? Any help is appreciated.
You had several issues. The main being your regex just parsing up to lat, not lon.
What changed:
m/Upper Left\s+[(]\s+\d{1,6}[.]\d{1,3}[\,]\s+\d{1,6}[.]\d{1,3}[)]\s+[(](\d{1,3})d(\d{1,2})['](\d{1,2})[.](\d{1,2})/ig
m/Upper Left\s+[(]\s+\d{1,6}[.]\d{1,3}[\,]\s+\d{1,7}[.]\d{1,3}[)]\s+[(](\d{1,3})d(\d{1,2})['](\d{1,2})[.](\d{1,2})"([WE])[\,]\s(\d{1,3})d(\d{1,2})['](\d{1,2})[.](\d{1,2})"([NS])/ig
^-- Your test number was 7-digit big ^-- (1) ^-- (2) ^-- (3)
At the ending: (1) added group to deal with W/E (([WE])). (2) Added groups to extract lon number. (3) Added group to deal with N/S (([NS])).
Your code, corrected:
if ($string=~ m/Upper Left\s+[(]\s+\d{1,6}[.]\d{1,3}[\,]\s+\d{1,7}[.]\d{1,3}[)]\s+[(](\d{1,3})d(\d{1,2})['](\d{1,2})[.](\d{1,2})"([WE])[\,]\s(\d{1,3})d(\d{1,2})['](\d{1,2})[.](\d{1,2})"([NS])/ig) {
$upperLeft = "lat=" . $1 . 'd' . $2 . "'" . $3 . "." . $4 . '"' . $5 . " long=" . $6 . 'd' . $7 . "'" . $8 . "." . $9 . '"' . $10;
print $upperLeft. "\n";
}
Output:
lat=117d38'28.21"W long=33d54'8.47"N