0

I have an input file named test.txt like this:

Homo sapiens
Mus musculus
Rat rattus rattus

I want to use a for loop here and loop through each line. Some thing like this:

for i in "`cat test.txt`"
do
        fn=store_name
        do something else > ${fn}.txt
done

Since each line has a space between names I used double quotes in cat test.txt. I want to make a variable fn which attaches _ between these names of the lines so my fn becomes Homo_sapiens and Mus_musculus and if I have Rat rattus rates it becomes Rat_rattus_rattus

How can I achieve this?

slm
  • 363,520
  • 117
  • 767
  • 871
user3138373
  • 2,441
  • 6
  • 29
  • 44
  • 1
    [don't read lines with "for"](http://mywiki.wooledge.org/DontReadLinesWithFor) – glenn jackman Aug 01 '18 at 20:23
  • I have to 2nd that comment, don't use `for` to read lines, it's just over complicating it when there are so many cleaner safer ways to do this. – slm Aug 01 '18 at 20:27

5 Answers5

5

Use tr to transliterate a space to an underscore:

while read line
do
    echo ${line} | tr -s " " "_"
done < test.txt

Homo_sapiens Mus_musculus Rat_rattus_rattus

JRFerguson
  • 14,570
  • 3
  • 34
  • 40
4

Using awk:

awk '{OFS="_";}{$1=$1; print}' test.txt

Using a loop:

while read -r line; do 
  line=${line// /_} 
  command using "$line"
done<test.txt
jesse_b
  • 35,934
  • 12
  • 91
  • 140
2

I'd use sed and read its output with a loop:

sed 's/[[:space:]]\+/_/g' test.txt | while IFS= read -r line; do 
    process "$line" however
done > some.output.file
glenn jackman
  • 84,176
  • 15
  • 116
  • 168
0

Here's a quick for loop that uses sed to get it done:

for file in $(sed "s/ /_/g" test.txt); do echo "test" > $file; done

Just replace the echo command with whatever it is you want to do.

I use commands like this all the time though out the day.

-1

Someone gave an answer with tr and someone else gave one with awk, now here's how to do it with sed:

for i in "`cat test.txt`"
do
    fn="$(echo "$i" |sed -e 's/ /_/g')"
    'do something else' > $fn.txt
done
Beam Davis
  • 199
  • 5
  • My point being there are about a hundred ways to do this...and he did tag his question with "sed". – Beam Davis Aug 01 '18 at 19:44
  • 1
    I don't understand why you are using a `for` loop instead of `while read`. Also why are you modifying `IFS` instead of just quoting your command substitution like op has done? Finally, you should use `$( ... )` over backticks. – jesse_b Aug 01 '18 at 19:54
  • 1
    [don't read lines with "for"](http://mywiki.wooledge.org/DontReadLinesWithFor) – glenn jackman Aug 01 '18 at 20:23
  • Modified to use quotes instead of IFS. As for "for" vs. "while", six one way, half-a-dozen the other. Also, nothing wrong with backticks if you have no quotes inside the command being called. – Beam Davis Aug 01 '18 at 22:14
  • Using "for" loop instead of "while" loop also doesn't matter in this case, because we don't want to handle blank lines anyway. – Beam Davis Aug 01 '18 at 22:22