简体   繁体   English

命令行中的for循环运行bash脚本逐行从文本文件读取

[英]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. 我有一个bash脚本,要求两个参数之间留有空格。 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. 一个while循环可能是您需要的。 Put the space separated strings in the file text.file : text.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. 'cat text.file'是字符串文字, $(cat text.file)会扩展为命令输出,但是cat是无用的,因为bash可以使用重定向来读取文件,并且带有引号的情况下,它将被视为单个参数,并且不带引号将在空格标签和换行符处分开。

Bash syntax to read a file line by line, but will be slow for big files Bash语法逐行读取文件,但是对于大文件将很慢

while IFS= read -r line; do ... "$line"; done < text.file
  • unsetting IFS for read command preserves leading spaces 取消为读取命令设置IFS会保留前导空格
  • -r option preserves \\ -r选项保留\\

another way, to read whole file is content=$(<file) , note the < inside the command substitution. 读取整个文件的另一种方法是content=$(<file) ,注意命令替换中的< 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 oldsetf用于存储当前set -fset +f设置
  • oldifs used to store current IFS 用于存储当前IFS oldifs
  • IFS=$'\\n' to split on newlines (multiple newlines will be treated as one) IFS=$'\\n'以换行符分割(多个换行符将被视为一个)
  • set -f avoid glob expansion for example in case line contains single * set -f避免glob扩展,例如在行包含单个*情况下
  • note () around $() to store the result of splitting to an array $() ()周围的note ()存储拆分结果到数组

Don't use for to read files line by line 不要for逐行读取文件

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). 如果要创建一个由您所要求的文字确定的解决方案(使用for循环并解析文件中的行),我将使用由文件中的行数确定的迭代(如果它不是太大) 。

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. 但是,使用sjsam的解决方案可能会有更好的时间。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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