【问题标题】:sed variable substitution using string使用字符串替换 sed 变量
【发布时间】:2019-05-29 08:20:09
【问题描述】:

如何在没有输入文件的情况下将参数传递给 sed。 sed 是单引号,并且已经有管道。

git filter-branch -f --index-filter \
      'git ls-files -s | sed -i "s-\t\"*-&dirname/-" |
                GIT_INDEX_FILE=$GIT_INDEX_FILE.new \
                git update-index --index-info &&
       mv "$GIT_INDEX_FILE.new" "$GIT_INDEX_FILE"' HEAD

如果 dirname 是硬编码的,上面的代码可以正常工作。但我需要将命令行参数中的目录名传递给脚本。我正在尝试如下,但没有运气。

 'set subdir=$folder;git ls-files -s | sed -i "s-\t\"*-&$subdir/-" |

sed 说输入文件丢失。我不能直接将输入文件传递给 sed。我看到如下错误。

Rewrite 9c86de42b7f3228e3d45a278c8caf7e24c8e55cf (1/2) (0 seconds passed, remaining 0 predicted)
sed: no input files

【问题讨论】:

    标签: linux git sed git-filter-branch


    【解决方案1】:

    这里有两个选择。您可以评估 $subdir 以构建固定的 sed 命令,然后将其设置为过滤器;或者您可以评估 git filter-branch 将调用的 shell 片段中的变量。

    要理解后者,请意识到您的--index-filter 字符串变为an ordinary shell variable

    --index-filter)
        filter_index="$OPTARG"
    ;;
    

    那就是passed to eval:

    eval "$filter_index" < /dev/null ||
        die "index filter failed: $filter_index"
    

    eval 表示$filter_index 中的表达式(由您的--index-filter 参数设置)可以访问the filter-branch script 中的所有shell 变量和函数。不幸的是,它的 private 变量中没有一个包含您想要的表达式——但是您可以访问它的 environment 变量,这意味着您可以将值放入环境变量中。换句话说,您可以将subdir=&lt;whatever&gt; 作为环境 提供给您的原始表达式。

    无论如何,作为bk2204 answered,您需要删除-i 选项。除此之外,sed 的某些版本不接受 \t 作为制表符(可能你的,请注意这一点)。

    要更早地扩展变量,只需执行此操作。例如:

    ... --index-filter \
        'git ls-files -s | sed "s-\t\"*-&'$folder'/-" | ...
    

    (我自己在这里删除了-i)。请注意这如何退出单引号,扩展 $folder,然后重新输入单引号。如果$folder 可能包含空格,请务必在此处扩展时使用双引号:

    ... --index-filter \
        'git ls-files -s | sed "s-\t\"*-&'"$folder"'/-" | ...
    

    这里的引号嵌套非常棘手:单引号内的内容都是一个大字符串,作为在filter-branch 脚本中设置变量$filter_index 的参数提供。 eval 通过第二次评估运行它,分解成管道​​(git ls-files,通过管道传输到sed,通过管道传输到git update-index)并运行各种多个命令,所有这些命令的标准输入都重定向到/dev/null.

    【讨论】:

    • 我尝试了后者并且成功了。这是一个完整的答案,它节省了很多时间。 eval 似乎解决了嵌套时传递参数的问题。我会在进一步更新脚本时尝试一下。
    【解决方案2】:

    您正在使用sed -i,它会在适当的位置编辑其命令行参数(即文件名)。但是,您正在从标准输入读取数据并且没有提供任何命令行参数。如果您只想像这样过滤标准输入,请在您的 sed 命令中省略 -i

    【讨论】:

    • 我已将 cmd-line args 分配给变量文件夹并使用如下。但看到错误。 'git ls-文件-s | sed "s-\t\"-&$folder/-" | 重写 d97350e369514528ea545e200cf1481cdae3ac61 (1/2) (0 秒过去,剩余 0 预测) 忽略路径 /index.js mv: cannot stat '/home/apurb /git_poc/poc-apollo-server/.git-rewrite/t/../index.new':没有这样的文件或目录索引过滤器失败:git ls-files -s | sed "s-\t\" i>-&$文件夹/-" | GIT_INDEX_FILE=$GIT_INDEX_FILE.new \ git update-index --index-info && mv "$GIT_INDEX_FILE.new" "$GIT_INDEX_FILE"
    • $folder 中的值未正确传递,因此 git 命令失败。如果 $folder 值在 sed 中硬编码,则 git 命令正在工作。
    • 接受为答案。删除 sed 中的选项“-i”会忽略输入。此外,$folder 的单引号和双引号起到了 torek 所指出的作用。
    猜你喜欢
    • 2021-09-28
    • 1970-01-01
    • 2015-04-18
    • 2021-07-04
    • 1970-01-01
    • 1970-01-01
    • 2017-06-29
    • 1970-01-01
    • 2021-03-01
    相关资源
    最近更新 更多