11

我正在尝试编写简短的脚本和以下命令:

echo "aaa111 bbb111" | xargs -I {} echo {} | sed 's/111/222/g'

Returns aaa222 bbb222,这是我所期望的。

我期待下一个命令:

echo "aaa111 bbb111" | xargs -I {} echo $(echo {} | sed 's/111/222/g')

返回相同,但它返回aaa111 bbb111!这是为什么?


UPD:我想要实现的目标:

我有很多文件,如pic30-coff-gcc,pic30-coff-ag等,我需要为每个文件创建一个符号链接,如pic30-gcc->pic30-coff-gcc等。

所以我写了这个:

ls|grep 'coff-'|xargs -I {} ln -s {} $(echo {} | sed 's/coff-//g')

它不起作用:对于每个文件,它报告该文件存在。我检查了这样的命令:

ls|grep 'coff-'|xargs -I {} echo "ln -s {} $(echo {} | sed 's/coff-//g')"

是的,这sed部分不起作用:

ln -s pic30-coff-gcc pic30-coff-gcc
ln -s pic30-coff-gcc-4.0.3 pic30-coff-gcc-4.0.3
...

但如果我只是输入

echo "ln -s pic30-coff-gcc $(echo pic30-coff-gcc | sed 's/coff-//g')"

有用:

ln -s pic30-coff-gcc pic30-gcc

然后我用 编写了测试命令aaa111,它也不起作用。还是不明白,为什么。

4

4 回答 4

29

for循环答案正是我没有来这里阅读的。的整个目的xargs是避免这个循环。xargs对于这种特殊情况,可能不是最聪明的工具,但问题在于它。

这是我最终得到的解决方案。它可能并不完美,但仍然有效:

echo "aaa111 bbb111" | xargs -I {} sh -c "echo \$(echo {} | sed 's/111/222/g')"
# Outputs aaa222 bbb222

您可以想出同一命令的不同变体:

echo "aaa111 bbb111" | xargs -I {} sh -c 'echo $(echo {} | sed "s/111/222/g")'
echo "aaa111 bbb111" | xargs -I {} sh -c "echo \`echo {} | sed 's/111/222/g'\`"

这里的要点只是调用一个新的 shell,它将在用正确的内容xargs替换replace-str(here ) 之后执行命令替换。{}

于 2015-03-31T08:19:52.673 回答
13

$(echo {} | sed 's/111/222/g')xargs在作为参数传递给它之前进行评估。它会返回{}

因此:

echo "aaa111 bbb111" | xargs -I {} echo $(echo {} | sed 's/111/222/g')

是相同的

echo "aaa111 bbb111" | xargs -I {} echo {}
于 2014-03-23T10:27:40.693 回答
-1

您似乎只需要一个简单的循环:

for file in *coff*; do
  ln -s "${file}" "${file/coff-/}"
done
于 2014-03-23T10:28:57.857 回答
-1

这是另一种变体,它更改每个输入行以打印源和目标,然后强制xargs一次读取两个参数。

# aside: avoid ls | grep
printf '%s\n' coff-* |
sed 's/\(coff-\(.*\)\)/\1 \2/' |
xargs -n 2 ln -s

这显然很脆弱;如果您有名称包含空格的文件名,则它们将被错误地解析。

于 2021-02-18T06:08:32.957 回答