【问题标题】:Send each line as a single argument in bash在 bash 中将每一行作为单个参数发送
【发布时间】:2014-06-19 20:01:10
【问题描述】:

我在 bash 中有一个变量,类似于

filenames='file 1
file 2
file 3'

我需要将上述变量内容中的每一行作为单个参数发送给程序。但我不能对此感到震惊。这是我尝试过的:

python -c 'import sys; print sys.argv' $filenames
['-c', 'file', '1', 'file', '2', 'file', '3']

或

python -c 'import sys; print sys.argv' "$filenames"
['-c', 'file 1\nfile 2\nfile 3']

我期待的是这样的

['-c', 'file 1', 'file 2', 'file 3']

我也尝试过调整IFS 设置,但无法正确设置。对此有何想法?

【问题讨论】:

    标签: bash shell command-line-arguments


    【解决方案1】:
    $ export filenames="file 1
    file 2
    file 3"
    $ echo "$filenames" | xargs -d\\n python -c 'import sys; print sys.argv'
    ['-c', 'file 1', 'file 2', 'file 3']
    

    使用read 代替xargs 的另一种方式:

    #!/bin/bash
    filenames="file 1
    file 2
    file 3"
    cmd="python -c 'import sys; print sys.argv; print sys.stdin.readlines()'"
    while read file
    do
        args="$args \"$file\""
    done < <(echo "$filenames")
    echo $cmd $args
    echo `echo hi | sh -c "$cmd $args"`
    

    输出:

    $ ./test.sh 
    python -c 'import sys; print sys.argv; print sys.stdin.readlines()' "file 1" "file 2" "file 3"
    ['-c', 'file 1', 'file 2', 'file 3'] ['hi\n']
    

    【讨论】:

    • 哇!我以为xargs 为每一行输入运行一次命令,不是吗?
    • 另外,我还需要在 python 命令的stdin 中添加其他内容,所以我认为这不会以当前形式进行。
    • 不,您需要使用-n1 选项来获得该行为。默认情况下,它使用尽可能多的参数,以适合每次调用的一行(您可以使用 -s 和 -n 选项重新定义“适合”)。
    • 啊,评估。我有一种感觉,这将是解决方案。另外,while 循环可以转成这样:args="$(echo "$filenames" | sed 's/^\|$/"/g' | tr '\n' ' ')" :)
    【解决方案2】:

    如果您没有正确获得额外级别的引用,则使用eval 或sh -c 双重评估命令可能会导致奇怪的错误。我建议改用数组,或者只是将文件列表存储为数组:

    filearray=("file 1" "file 2" "file 3")
    python -c 'import sys; print sys.argv' "${filearray[@]}"
    

    或将其从换行符分隔的字符串转换为数组:

    filenames='file 1
    file 2
    file 3'
    oldIFS="$IFS"; IFS=$'\n'
    filearray=($filenames)
    IFS="$oldIFS"
    python -c 'import sys; print sys.argv' "${filearray[@]}"
    

    【讨论】:

    • +1 这是我一直想要的完美解决方案。非常感谢。
    【解决方案3】:

    只是添加另一个选项,

    OLDIFS=$IFS
    IFS='
    '
    set -- $filenames
    python -c 'import sys; print sys.argv; print sys.stdin.readlines()' "$@"
    IFS=$OLDIFS
    

    编辑: 添加代码以将旧值保存在 OLDIFS 中并在之后恢复它。 IFS='whatever' set -- $var 在单行上不起作用。

    【讨论】:

    • 我正在尝试IFS="\n" 之类的#facepalm。谢谢。
    • 在 bash 中,$'\n' 是文字换行符。
    • 嗯,我记得我也试过。哦,好吧。
    【解决方案4】:

    另一种选择:

    while read line ; do
      python -c 'import sys; print sys.argv' $line;
    done <(echo $filenames)
    

    【讨论】:

    • 不会因为没有引用的回声而破坏任何换行符吗?
    【解决方案5】:

    xargs 呢:

    $ seq 10 | xargs  python -c 'print __import__("sys").argv'
    ['-c', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10']
    

    【讨论】:

      猜你喜欢
      • 2014-06-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-11
      • 1970-01-01
      • 2020-09-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多