Creating multiple loops with string read from ascii files in bash

狂风中的少年 提交于 2019-12-24 22:42:41

问题


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:


  1. 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"
  1. 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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!