我有一个脚本s1
,输出用“,”分隔的数字列表,例如1,2,3,4
。现在我想将这些数字s2
作为参数提供给脚本,以便 s2 将在每个数字上运行并在单独的行中输出其结果。例如,如果 s2 将数字乘以二,这将是我正在寻找的结果:
2
4
6
8
我现在正在做的是:
s1 | xargs -d "," | xargs -n1 s2
但我觉得我这样做很愚蠢!所以我的问题是:
正确的做法是什么?
我的解决方案的问题是它调用 xargs 两次并迭代输入两次,这在我看来当然从性能角度来说是不合理的!答案xargs -d "," -n1
似乎不错,但我不确定它是否只迭代一次。如果确实如此,请在您的回答中验证这一点,我会接受它。顺便说一句,我不想使用 Perl,因为它仍然迭代两次,而且 Perl 在许多系统上可能不存在。
答案1
这也应该同样有效:
s1 | xargs -d "," -n1 s2
测试用例:
printf 1,2,3,4 | xargs -d ',' -n1 echo
结果:
1
2
3
4
如果s1
输出该列表后跟换行符,您需要将其删除,否则最后一次调用将是 with4\n
而不是4
:
s1 | tr -d '\n' | xargs -d , -n1 s2
答案2
如果s2
可以接受多个参数,你可以这样做:
(IFS=,; ./s2 $(./s1))
它暂时将 IFS 覆盖为逗号,全部在子 shell 中,以便看到由逗号分隔s2
的输出。s1
子 shell 是一种更改 IFS 的快捷方法,无需保存先前的值或重置它。
此答案的先前版本不正确,可能是由于剩余的 IFS 设置导致结果损坏。谢谢伊尔卡丘为了指出我的错误。
要手动循环输出并将它们单独提供给s2
,此处演示了 IFS 的保存和重置:
oIFS="$IFS"
IFS=,
for output in $(./s1); do ./s2 "$output"; done
IFS="$oIFS"
或者像以前一样在子 shell 中运行 IFS 位:
(
IFS=,
for output in $(./s1); do ./s2 "$output"; done
)
答案3
尝试这个:
s1 | perl -pe 's/,/\n/g' | xargs -n1 s2