我有一个文件输入可能有空行,我想跳过任何空行。
我正在尝试找到一个不需要使用 grep / tr 并将输出通过管道传输到 xargs 的解决方案
我使用以下 xarg 选项
-r如果没有参数,我不希望运行该命令。 -d '\n'新行是分隔符。
使用回显命令:
echo "" | xargs -r -d'\n' -I {} echo "test '{}'"
Run Code Online (Sandbox Code Playgroud)
输出:
test ''
Run Code Online (Sandbox Code Playgroud)
使用由空行组成的文件的命令:
xargs -a /tmp/test.txt -r -d'\n' -I {} echo "test '{}'"
Run Code Online (Sandbox Code Playgroud)
输出:
test ''
test ''
test ''
Run Code Online (Sandbox Code Playgroud)
我可以如上所述使用 grep,但我想知道是否可以仅使用 xargs 来完成。
grep 示例(工作):
grep -v -e '^$' /tmp/test.txt | xargs -r -d'\n' -I {} echo "test '{}'"
Run Code Online (Sandbox Code Playgroud)
-r-I不是忽略空元素,而是避免在输入没有元素时运行命令一次(尽管(也不是 BSD )不需要-J)。
您通常-r出于这个原因想要。
find . -criteria -print0 | xargs -0 ls -ld
Run Code Online (Sandbox Code Playgroud)
如果find没有找到任何东西,仍然会ls -d在没有参数的情况下运行,并且会列出..
所以你确实想要:
find . -criteria -print0 | xargs -r0 ls -ld
Run Code Online (Sandbox Code Playgroud)
如果什么也没找到,则ls根本不运行find。
请注意, 和-r都是-0GNU 扩展(同样,-d可移植性更差)。-r是某些 BSD 的默认行为,xargs包括 FreeBSD 和 NetBSD(尽管这使得它们不符合 POSIX)。
(无论如何,xargs在该特定示例中不需要像您一样find . -criteria -exec ls -ld {} +)。
据我所知,GNUxargs是唯一支持选项的实现-d,并且它不支持过滤掉特定参数值,无论是空值还是其他值,因此使用grep(grep -v '^$'或LC_ALL=C grep .) 是正确的方法。
如果您仍然想使用-a(另一个 GNU 扩展),例如为了让命令的 stdin 保持不变,并且使用支持 ksh 样式进程替换(ksh、zsh、bash)的 shell,您可以这样做:
xargs -rd '\n' -a <(grep -v '^$' test.txt) cmd --
Run Code Online (Sandbox Code Playgroud)
xargs -d '\n' -I{} -a <(grep -v '^$' test.txt) cmd -- {}
Run Code Online (Sandbox Code Playgroud)
(rc、akanga、es、fish 和 yash shell 具有相同的功能,但语法不同)。
注意-0是 like -d '\0',所以与 冲突-d '\n'。您必须选择d您想要的限制器。后者将优先,-0 -d '\n'因为它排在最后。
-0是首选分隔符,因为它是不能出现在命令参数或文件路径中的单字节值。,与现在在许多其他实现中发现的-0相反(包括大多数 BSD、Solaris、busybox、toybox、ast-open 的实现)。对于不支持的实现(即除 GNU 之外的所有实现),您可以使用:-dxargsxargs-dxargs
tr '\n' '\0' | xargs -0 ...
Run Code Online (Sandbox Code Playgroud)
代替 GNU 的:
xargs -d '\n' ...
Run Code Online (Sandbox Code Playgroud)
如果使用zsh,而不是使用xargs,您可以这样做:
for arg ( ${(f)"$(<test.txt)"} ) cmd -- $arg
Run Code Online (Sandbox Code Playgroud)
参数f扩展标志在换行符上拆分,并且由于${...}未加引号,所以空元素将被删除。
和bash:
readarray -t args < test.txt &&
for arg in "${args[@]}"; do
[ -z "$arg" ] || cmd -- "$arg"
done
Run Code Online (Sandbox Code Playgroud)
您还可以通过不加引号的数组扩展来进行空删除,但是您还需要禁用通配符和拆分,这也是在未加引号的参数扩展时完成的:
IFS=; set -o noglob
readarray -t args < test.txt &&
for arg in ${args[@]}; do
cmd -- "$arg"
done
Run Code Online (Sandbox Code Playgroud)
您还可以执行以下操作:
while IFS= read <&3 -r arg || [ -n "$arg" ]; do
[ -z "$arg" ] || cmd -- "$arg" 3<&-
done 3< test.txt
Run Code Online (Sandbox Code Playgroud)
这是标准sh语法。