问题
I want to create an internal loop inside a loop with strings which are read from ascii files in a bash script. I have two input ascii files which contain a list of strings:
files.txt:
filename1
filename2
polls.txt:
CO
NOx
SOx
I used IFS and read as following :
while IFS= read -r file; do
printf '%s\n' "$file"
while IFS= read -r poll; do
printf '%s\n' "$poll"
ogrinfo $Database_maindir/$file".shp" -sql "ALTER TABLE $file ADD COLUMN $poll float"
done < "$Database_maindir/polls.txt"
done < "$Database_maindir/files.txt"
I get the following prints and errors:
CO
CO
FAILURE:
Unable to open datasource `/home/CO.shp' with the following drivers.
It reads only the string of "polls.txt".
The correct output should be:
filename1
CO
ogrinfo /home/"filename1.shp" -sql "ALTER TABLE filename1 ADD COLUMN CO float"
NOx
ogrinfo /home/"filename1.shp" -sql "ALTER TABLE filename1 ADD COLUMN NOx float"
Sox
ogrinfo /home/"filename1.shp" -sql "ALTER TABLE filename1 ADD COLUMN Sox float"
filename2
CO
ogrinfo /home/"filename2.shp" -sql "ALTER TABLE filename2 ADD COLUMN CO float"
NOx
ogrinfo /home/"filename2.shp" -sql "ALTER TABLE filename2 ADD COLUMN NOx float"
Sox
ogrinfo /home/"filename2.shp" -sql "ALTER TABLE filename2 ADD COLUMN Sox float"
So, for each file (e.g. filename1, filename2) I want to execute a COMMAND (e.g. an ogrinfo command which updates the columns of a file where the columns are different pollutants listed in the polls.txt.
In the first loop I want to read the strings from the files.txt and keep the string $file with the name of the string (e.g. filename1). In the second loop I want to read the strings from "polls.txt" and keep the string $poll (e.g.CO).
However, it seems that for the first loop it reads the string from the first file it finds , meaning the "polls.txt", so $file gives the string "CO".
How I could define that the first loop should read the second txt file?
回答1:
Perhaps you can try with awk :
awk '
NR == FNR {
a[$0]
next
}
{
for ( i in a )
printf( "system ogringo %s %s\n" , $0 , i )
}
' polls.txt files.txt
I know nothing about sql but perhaps you can have only one command for each file.
回答2:
- Use dedicated file descriptors. That way you are 100% sure each
read
reads from the proper stream. And the commands inside the loop also don't read from the stream.
while IFS= read -r -u 3 file; do
printf '%s\n' "$file"
while IFS= read -r -u 4 poll; do
printf '%s\n' "$poll"
echo ogrinfo $Database_maindir/$file".shp" -sql "ALTER TABLE $file ADD COLUMN $poll float"
done 4< "$Database_maindir/polls.txt"
done 3< "$Database_maindir/files.txt"
- Use an unreadable script which first merges two files together by repeating the first one the number of lines the second one has, and then repeating each line in the second one by the number of lines in the first and then runs xargs (ideas for repeating from here and here)
paste <(
awk -v nr=$(wc -l <polls.txt) \
'{for (i = 1; i <= nr; i++) print}' files.txt
) <(
seq $(wc -l <files.txt) |
xargs -n1 cat polls.txt
) |
xargs -n2 sh -c 'echo ogrinfo "$1".shp -sql "ALTER TANLE $1 ADD COLUMN $2 float"' --
来源:https://stackoverflow.com/questions/54870417/creating-multiple-loops-with-string-read-from-ascii-files-in-bash