我正在尝试获取一个函数的输出并将其传递给另一个函数。
set -x
OUTPUT=$(git diff --name-only --diff-filter=AM develop... | sed 's/.*/"&"/')
./bin/phpcs $OUTPUT
我的主要问题是第一个函数返回文件列表,并且文件可能包含空格。因此,我将它们用双引号引起来,但是当我将其传递给其他函数时,会添加其他单引号。
输出:
++ git diff --name-only --diff-filter=AM develop...
++ sed 's/.*/"&"/'
+ OUTPUT='"test file.php"
"testfile.php"'
+ ./bin/phpcs '"test' 'file.php"' '"testfile.php"'
呼叫的主要最终目标等于:
./bin/phpcs "test file.php" "testfile.php"
答案1
您的问题是您正在向 输出的文本添加双引号git diff
。这会破坏路径名,并使正确解析文件列表变得更加困难,特别是当任何路径名恰好包含引号时。
您在跟踪输出中看到的单引号只是添加了 ,bash
以便更容易地查看字符串是如何分隔的(例如,显示"test
、file.php"
、 和"testfile.php"
是三个单独的参数)。请记住,shell 的跟踪输出是调试输出,旨在提示您 shell 正在做什么,通常不是实际的由 shell 运行的代码。
要安全地使用输出的路径名git diff --name-only
,请考虑使用该-z
选项。这会导致git
将路径名输出为空分隔列表。然后,您可以用来xargs -0
对该列表的元素执行任何命令:
git diff --name-only -z --diff-filter=AM develop... |
xargs -0 ./bin/phpcs
您还可以将文件列表读入数组。例如,在bash
外壳中:
readarray -d '' -t names < <( git diff --name-only -z --diff-filter=AM develop... )
./bin/phpcs "${names[@]}"
这显然依赖于git diff
不输出太多名字。
答案2
如果您可以保证文件名不包含换行符,您可以使用它们来分隔文件名并将它们弹出到数组中:
OIFS=$IFS IFS=$'\n'
files=( $(git diff --name-only --diff-filter=AM develop...) )
IFS=$OIFS
现在您可以将数组插入为带引号的字符串列表:
./bin/phpcs "${files[@]}"
这不会在 POSIXsh
或dash
.您需要使用bash
支持数组的 shell
答案3
不添加单引号。bash -x
只是向您显示看到了哪些字面参数。正如$OUTPUT
未引用的那样,分词作用于空格和换行符。它们"
是变量的一部分,与 shell 解析无关。
你可以这样做:
eval ./bin/phpcs $OUTPUT
不过,roaima 的数组方法似乎更好。