我有一个文件输入可能有空行,我想跳过任何空行。
我正在尝试找到一个不需要使用 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
都是-0
GNU 扩展(同样,-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 之外的所有实现),您可以使用:-d
xargs
xargs
-d
xargs
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
语法。