如何将文本文件的每一行解析为命令的参数?

Woj*_*chF 52 command-line shell-script

我正在编写一个脚本,该脚本将.txt文件名作为参数,逐行读取文件,并将每一行传递给命令。例如,它运行command --option "LINE 1"、 thencommand --option "LINE 2"等。命令的输出被写入另一个文件。我该怎么做?我不知道从哪里开始。

ctr*_*lor 37

另一种选择是xargs

使用 GNU xargs

xargs -a file -I{} -d'\n' command --option {} other args
Run Code Online (Sandbox Code Playgroud)

{} 是文本行的占位符。

其他xargs通常没有-a, -d,但有些有-0NUL 分隔的输入。有了这些,你可以:

< file tr '\n' '\0' | xargs -0 -I{} command --option {} other args
Run Code Online (Sandbox Code Playgroud)

在符合 Unix 的系统上(-I在 POSIX 中是可选的,只有符合 UNIX 的系统才需要),您需要预处理输入以引用预期格式的行xargs

< file sed 's/"/"\\""/g;s/.*/"&"/' |
  xargs -E '' -I{} command --option {} other args
Run Code Online (Sandbox Code Playgroud)

但是请注意,某些xargs实现对参数的最大大小有非常低的限制(例如,在 Solaris 上为 255,这是 Unix 规范允许的最小值)。


kon*_*box 31

使用while read循环:

: > another_file  ## Truncate file.

while IFS= read -r LINE; do
    command --option "$LINE" >> another_file
done < file
Run Code Online (Sandbox Code Playgroud)

另一种是按块重定向输出:

while IFS= read -r LINE; do
    command --option "$LINE"
done < file > another_file
Run Code Online (Sandbox Code Playgroud)

最后是打开文件:

exec 4> another_file

while IFS= read -r LINE; do
    command --option "$LINE" >&4
    echo xyz  ## Another optional command that sends output to stdout.
done < file
Run Code Online (Sandbox Code Playgroud)

如果其中一个命令读取输入,这将是使用另一种FD输入这样的命令不会吃一个好主意(这里假设kshzshbash-u 3,使用<&3替代便携):

while IFS= read -ru 3 LINE; do
    ...
done 3< file
Run Code Online (Sandbox Code Playgroud)

最后接受参数,你可以这样做:

#!/bin/bash

FILE=$1
ANOTHER_FILE=$2

exec 4> "$ANOTHER_FILE"

while IFS= read -ru 3 LINE; do
    command --option "$LINE" >&4
done 3< "$FILE"
Run Code Online (Sandbox Code Playgroud)

哪一个可以运行为:

bash script.sh file another_file
Run Code Online (Sandbox Code Playgroud)

额外的想法。随着bash使用readarray

readarray -t LINES < "$FILE"

for LINE in "${LINES[@]}"; do
    ...
done
Run Code Online (Sandbox Code Playgroud)

注意:IFS=如果您不介意修剪前导和尾随空格的行值,则可以省略。


mii*_*otu 11

准确地保持这个问题:

#!/bin/bash

# xargs -n param sets how many lines from the input to send to the command

# Call command once per line
[[ -f $1 ]] && cat $1 | xargs -n1 command --option

# Call command with 2 lines as args, such as an openvpn password file
# [[ -f $1 ]] && cat $1 | xargs -n2 command --option

# Call command with all lines as args
# [[ -f $1 ]] && cat $1 | xargs command --option
Run Code Online (Sandbox Code Playgroud)

  • 像魅力一样工作:-) (2认同)

Ste*_*ler 9

我找到的最佳答案是:

for i in `cat`; do "$cmd" "$i"; done < $file
Run Code Online (Sandbox Code Playgroud)

编辑:

……四年后……

经过几次否决票和更多经验后,我现在推荐以下内容:

xargs -l COMMAND < file
Run Code Online (Sandbox Code Playgroud)

  • 这将为文件中的每个 *** 字 *** 调用一次命令。此外,你应该总是引用对 shell 变量的引用(如在 `do "$cmd" "$i";` 中),除非你有理由不这样做;如果文件本身包含一个 `*` 作为单词,你的代码将运行 `$cmd *`,当然,它会运行带有当前目录中文件列表的命令。 (4认同)
  • +1。如果每一行只包含所使用的命令所需的输入而没有空格,这将工作正常。 (2认同)
  • 这是有效的!(稍后编辑`xargs -l COMMAND &lt;文件`)。谢谢! (2认同)