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
,但有些有-0
NUL 分隔的输入。有了这些,你可以:
< 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输入这样的命令不会吃一个好主意(这里假设ksh
,zsh
或bash
为-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)
我找到的最佳答案是:
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)