【问题标题】:why shell for expression cannot parse xargs parameter correctly为什么 shell for expression 无法正确解析 xargs 参数
【发布时间】:2021-03-27 22:00:23
【问题描述】:

我有一个黑名单来保存标签 ID 列表,例如1-3,7-9,其实就是代表1,2,3,7,8,9。并且可以通过下面的shell扩展它

for i in {1..3,7..9}; do for j in {$i}; do echo -n "$j,"; done; done
1,2,3,7,8,9

但首先我应该将- 转换为..

echo -n "1-3,7-9" | sed 's/-/../g'
1..3,7..9

然后将其作为参数放入for表达式中

echo -n "1-3,7-9" | sed 's/-/../g'  | xargs -I @ for i in {@}; do for j in {$i}; do echo -n "$j,"; done; done
zsh: parse error near `do'

echo -n "1-3,7-9" | sed 's/-/../g'  | xargs -I @ echo @
1..3,7..9

但是for 表达式无法正确解析,为什么会这样?

【问题讨论】:

    标签: shell for-loop xargs


    【解决方案1】:

    因为您没有做任何事情来阻止最外层 shell 拾取您打算由 xargs 运行的特殊关键字和字符(dofor$ 等)。

    xargs 不是内置的 shell;它从它的 arguments 获取您希望它为 stdin 上的每个元素运行的命令行。就像任何其他程序一样,如果您希望 ; 或任何其他特殊序列在参数中成为 bash,您需要以某种方式对其进行转义。

    在我看来,您在这里真正想要的是在子shell 中为每个输入元素调用一个命令(嵌套的for 循环)。

    我想出了这个;这似乎是工作:

    echo -n "1-3,7-9" \
    | sed 's/-/../g'  \
    | xargs -I @  \
    bash -c "for i in {@}; do for j in {\$i}; do echo -n \"\$j,\"; done; done;"
    

    给出:

    {1..3},{7..9},
    

    【讨论】:

    • 谢谢!但实际上我想要的是将1-3,7-9 转换为1,2,3,7,8,9
    【解决方案2】:

    可以使用下面的shell来实现这个

    # Mac newline need special treatment
    echo "1-3,7-9" | sed -e 's/-/../g' -e $'s/,/\\\n/g' | xargs -I@ echo 'for i in {@}; do echo -n "$i,"; done' | bash
    1,2,3,7,8,9,%
    
    
    #Linux
    echo "1-3,7-9" | sed -e 's/-/../g' -e 's/,/\n/g' | xargs -I@ echo 'for i in {@}; do echo -n "$i,"; done' | bash
    1,2,3,7,8,9,
    

    但是这种方式使用起来有点复杂,也许awk更直观

    # awk
    echo "1-3,7-9,11,13-17" | awk '{n=split($0,a,","); for(i=1;i<=n;i++){m=split(a[i],a2,"-");for(j=a2[1];j<=a2[m];j++){print j}}}' | tr '\n' ','
    1,2,3,7,8,9,11,13,14,15,16,17,%
    

    【讨论】:

      【解决方案3】:
      echo -n "1-3,7-9" | perl -ne 's/-/../g;$,=",";print eval $_' 
      

      【讨论】:

      • 请在您的回答中添加一些解释。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-30
      • 1970-01-01
      • 1970-01-01
      • 2012-12-07
      相关资源
      最近更新 更多