user1938965
user1938965

Reputation: 163

using for loop and pass variables to a command

I have two files, table1.txt and table2.txt, with the first column having characters chr1, chr2, chr3 in both. I want to iterate a command such that it greps the rows containing only one of chr1, chr2, chr3 from both tables, and passes this subset of the table (say all rows with chr1) to another command (say cat, which takes in the two tables as input). The output is then saved as a file (say new_chr1.txt for operation on chr1 rows).

Following are dummy representations of the two tables:

table1.txt:

chr1    5   55  1
chr1    14  62  1
chr1    47  97  1
chr2    4   52  1
chr2    20  70  1
chr2    25  75  1
chr3    3   52  1
chr3    6   56  1
chr3    10  60  1

table2.txt:

chr1    0       199
chr1    200     399
chr1    400     599
chr2    600     799
chr2    800     999
chr2    1000    1199
chr3    1200    1399
chr3    1400    1599
chr3    1600    1799

I tried the following code:

for i in chr1 chr2 chr3
mkfifo table1
mkfifo table2
grep -w $i table1.txt > table1 &
grep -w $i table2.txt > table2 &
cat table1 table2 > new_$i.txt
done

Following is copied from my screen to show the errors I get at each stage:

for i in chr1 chr2 chr3
mkfifo table1
-bash: syntax error near unexpected token `mkfifo'
mkfifo table2
grep -w $i table1.txt > table1 &
[5] 1969
grep -w $i table2.txt > table2 &
[6] 1970

cat table1 table2 > new_$i.txt
[5]   Exit 1                  grep -w $i table1.txt > table1
[6]   Exit 1                  grep -w $i table2.txt > table2
done
-bash: syntax error near unexpected token `done'

I am not able to figure out what's going wrong. If I just run the above command without the for loop and without mkfifo, and by specifying the patterns to be matched (say chr1), it works fine. Any idea how to make this work?

BTW, in my actual code, I have to run another command, not cat, on the two greped files.

Upvotes: 1

Views: 802

Answers (2)

Jonathan Leffler
Jonathan Leffler

Reputation: 754090

A for loop needs a do to start the body of the loop:

for i in chr1 chr2 chr3
do
    mkfifo table1
    mkfifo table2
    grep -w $i table1.txt > table1 &
    grep -w $i table2.txt > table2 &
    wait          # Make sure the grep commands are complete before using the results
    cat table1 table2 > new_$i.txt
done

There may be other problems, but that's why you got the '-bash: syntax error near unexpected token `mkfifo'' error (and the done error was because it didn't think you were in a for loop yet).

Incidentally, you should use wait before launching the final command in the loop to be sure the grep operations are complete.

Upvotes: 2

parkydr
parkydr

Reputation: 7782

You can achieve the same thing with the following:

for i in chr1 chr2 chr3
do
        grep -hw $i table[12].txt > new_$i.txt
done

It greps both table1.txt and table2.txt. The -h stops the file names from being printed on each line.

If you want to do them separately, you can just append the output of table2 with >>:

grep -w $i table1.txt > new_$i.txt
grep -w $i table2.txt >> new_$i.txt

Upvotes: 1

Related Questions