简体   繁体   中英

For loop in command line runs bash script reading from text file line by line

I have a bash script which asks for two arguments with a space between them. Now I would like to automate filling out the prompt in the command line with reading from a text file. The text file contains a list with the argument combinations.

So something like this in the command line I think;

for line in 'cat text.file' ; do script.sh ; done

Can this be done? What am I missing/doing wrong?

Thanks for the help.

A while loop is probably what you need. Put the space separated strings in the file text.file :

cat text.file
bingo yankee
bravo delta

Then write the script in question like below.

#!/bin/bash
while read -r arg1 arg2
do
 /path/to/your/script.sh "$arg1" "$arg2"
done<text.file

'cat text.file' is a string literal, $(cat text.file) would expand to output of command however cat is useless because bash can read file using redirection, also with quotes it will be treated as a single argument and without it will split at space tab and newlines.

Bash syntax to read a file line by line, but will be slow for big files

while IFS= read -r line; do ... "$line"; done < text.file
  • unsetting IFS for read command preserves leading spaces
  • -r option preserves \\

another way, to read whole file is content=$(<file) , note the < inside the command substitution. so a creative way to read a file to array, each element a non-empty line:

read_to_array () {
    local oldsetf=${-//[^f]} oldifs=$IFS
    set -f
    IFS=$'\n' array_content=($(<"$1")) IFS=$oldifs
    [[ $oldsetf ]]||set +f
}

read_to_array "file"
for element in "${array_content[@]}"; do ...; done
  • oldsetf used to store current set -f or set +f setting
  • oldifs used to store current IFS
  • IFS=$'\\n' to split on newlines (multiple newlines will be treated as one)
  • set -f avoid glob expansion for example in case line contains single *
  • note () around $() to store the result of splitting to an array

Don't use for to read files line by line

Try something like this:

#!/bin/bash
ARGS= 
while IFS= read -r line; do
    ARGS="${ARGS} ${line}"
done < ./text.file

script.sh "$ARGS"

This would add each line to a variable which then is used as the arguments of your script.

If I were to create a solution determined by the literal of what you ask for (using a for loop and parsing lines from a file) I would use iterations determined by the number of lines in the file (if it isn't too large).

Assuming each line has two strings separated by a single space (to be used as positional parameters in your script:

file="$1"
f_count="$(wc -l < $file)"
for line in $(seq 1 $f_count)
do

    script.sh $(head -n $line $file | tail -n1) && wait

done

You may have a much better time using sjsam's solution however.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM