优化 xargs 参数枚举
optimize xargs argument enumeration
xargs 参数枚举的这种用法可以优化得更好吗?
目的是在实际命令的中间注入单个参数。
我愿意:
echo {1..3} | xargs -I{} sh -c 'for i in {};do echo line $i here;done'
或
echo {1..3} | for i in $(xargs -n1);do echo line $i here; done
我得到:
line 1 here
line 2 here
line 3 here
这是我需要的,但我想知道是否可以避免循环和临时变量?
也许是这个?
echo {1..3} | tr " " "\n" | xargs -n1 sh -c ' echo "line [=10=] here"'
tr
用换行符替换空格,所以 xargs
看到三行。如果有更好(更有效)的解决方案,我不会感到惊讶,但这个非常简单。
请注意,我已经修改了我之前的答案以删除 {}
的使用,评论中建议这样做是为了消除潜在的代码注入漏洞。
您需要用换行符将 xargs
的输入分隔开:
echo {1..3}$'\n' | xargs -I% echo line % here
对于数组扩展,你可以使用printf
:
ar=({1..3})
printf '%s\n' "${ar[@]}" | xargs -I% echo line % here
(如果只是为了输出,不用xargs
也可以用:
printf 'line %s here\n' "${ar[@]}"
)
GNU sed 有一个鲜为人知的特性。您可以将 e
标志添加到 s
命令,然后 sed 执行模式 space 中的任何内容,并将模式 space 替换为该命令的输出。
如果您真的只对 echo 命令的输出感兴趣,您可以试试这个 GNU sed 示例,它消除了临时变量、循环(以及 xargs):
echo {1..3} | sed -r 's/([^ ])+/echo "line here"\n/ge
- 它获取一个令牌(即由 space 分隔的任何内容)
- 用
echo "line here"\n
命令替换它,</code>替换为令牌</li>
<li>然后执行 echo </li>
<li>将 echo 命令的输出放回模式 space</li>
<li>表示输出三个echo的结果</li>
</ul>
<hr>
<p>但获得所需输出的更好方法是跳过执行并直接在 sed 中进行转换,如下所示:</p>
<pre><code>echo {1..3} | sed -r 's/([^ ])+ ?/line here\n/g'
不用 xargs
试试。在大多数情况下 xargs
是矫枉过正的。
根据你真正想要的,你可以选择像
这样的解决方案
# Normally you want to avoid for and use while, but here you want the things splitted.
for i in $(echo {1 2 3} );do
echo line $i here;
done
# When you want 1 line turned into three, `tr` can help
echo {1..3} | tr " " "\n" | sed 's/.*/line & here/'
# printf will repeat itself when there are parameters left
printf "line %s here\n" $(echo {1..3})
# Using the printf feature you can avoid the echo
printf "line %s here\n" {1..3}
xargs 参数枚举的这种用法可以优化得更好吗? 目的是在实际命令的中间注入单个参数。
我愿意:
echo {1..3} | xargs -I{} sh -c 'for i in {};do echo line $i here;done'
或
echo {1..3} | for i in $(xargs -n1);do echo line $i here; done
我得到:
line 1 here
line 2 here
line 3 here
这是我需要的,但我想知道是否可以避免循环和临时变量?
也许是这个?
echo {1..3} | tr " " "\n" | xargs -n1 sh -c ' echo "line [=10=] here"'
tr
用换行符替换空格,所以 xargs
看到三行。如果有更好(更有效)的解决方案,我不会感到惊讶,但这个非常简单。
请注意,我已经修改了我之前的答案以删除 {}
的使用,评论中建议这样做是为了消除潜在的代码注入漏洞。
您需要用换行符将 xargs
的输入分隔开:
echo {1..3}$'\n' | xargs -I% echo line % here
对于数组扩展,你可以使用printf
:
ar=({1..3})
printf '%s\n' "${ar[@]}" | xargs -I% echo line % here
(如果只是为了输出,不用xargs
也可以用:
printf 'line %s here\n' "${ar[@]}"
)
GNU sed 有一个鲜为人知的特性。您可以将 e
标志添加到 s
命令,然后 sed 执行模式 space 中的任何内容,并将模式 space 替换为该命令的输出。
如果您真的只对 echo 命令的输出感兴趣,您可以试试这个 GNU sed 示例,它消除了临时变量、循环(以及 xargs):
echo {1..3} | sed -r 's/([^ ])+/echo "line here"\n/ge
- 它获取一个令牌(即由 space 分隔的任何内容)
- 用
echo "line here"\n
命令替换它,</code>替换为令牌</li> <li>然后执行 echo </li> <li>将 echo 命令的输出放回模式 space</li> <li>表示输出三个echo的结果</li> </ul> <hr> <p>但获得所需输出的更好方法是跳过执行并直接在 sed 中进行转换,如下所示:</p> <pre><code>echo {1..3} | sed -r 's/([^ ])+ ?/line here\n/g'
不用 xargs
试试。在大多数情况下 xargs
是矫枉过正的。
根据你真正想要的,你可以选择像
# Normally you want to avoid for and use while, but here you want the things splitted.
for i in $(echo {1 2 3} );do
echo line $i here;
done
# When you want 1 line turned into three, `tr` can help
echo {1..3} | tr " " "\n" | sed 's/.*/line & here/'
# printf will repeat itself when there are parameters left
printf "line %s here\n" $(echo {1..3})
# Using the printf feature you can avoid the echo
printf "line %s here\n" {1..3}