使用字符串

时间:2019-05-28 23:02:45

标签: linux git sed git-filter-branch

如何在没有输入文件的情况下将参数传递给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

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

 '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

2 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分:2)

您在这里有两个选择。您可以评估$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=<whatever>作为环境提供给原始表达式。

无论如何,作为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_index脚本中设置变量filter-branch的参数提供。 eval通过第二次评估运行它,分解为管道(git ls-files,通过管道传输到sed,通过管道传输到git update-index),并运行各种多个命令,所有这些对象的标准输入都重定向到/dev/null