意外的bash引用行为

时间:2016-12-04 20:16:42

标签: bash

我有一个bash命令管道,如下所示:

cat report.json | \
./jq '.outdated.dependencies[] |  {group, name, "version": .available.milestone} | .group + ":" + .name + ":" + .version' | \
xargs -0 -d'\n' -I DEPENDENCY echo ./gradlew clean test -PdependencyOverrides=DEPENDENCY

此命令的输出为:

./gradlew clean test -PdependencyOverrides="org.flywaydb:flyway-core:4.0.3"
./gradlew clean test -PdependencyOverrides="org.hibernate:hibernate-c3p0:5.2.5.Final"
./gradlew clean test -PdependencyOverrides="org.hibernate:hibernate-core:5.2.5.Final"
./gradlew clean test -PdependencyOverrides="org.hibernate:hibernate-entitymanager:5.2.5.Final"
./gradlew clean test -PdependencyOverrides="org.hibernate:hibernate-java8:5.2.5.Final"
./gradlew clean test -PdependencyOverrides="org.hibernate:hibernate-validator:5.3.3.Final"
./gradlew clean test -PdependencyOverrides="com.fasterxml.jackson.core:jackson-databind:2.8.5"
./gradlew clean test -PdependencyOverrides="com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.8.5"
./gradlew clean test -PdependencyOverrides="javax.el:javax.el-api:3.0.1-b04"
./gradlew clean test -PdependencyOverrides="org.apache.logging.log4j:log4j-api:2.7"
./gradlew clean test -PdependencyOverrides="org.apache.logging.log4j:log4j-core:2.7"
./gradlew clean test -PdependencyOverrides="org.apache.logging.log4j:log4j-slf4j-impl:2.7"
./gradlew clean test -PdependencyOverrides="org.mockito:mockito-core:2.2.28"
./gradlew clean test -PdependencyOverrides="org.postgresql:postgresql:9.4.1212"
./gradlew clean test -PdependencyOverrides="com.getsentry.raven:raven-log4j2:7.8.1"
./gradlew clean test -PdependencyOverrides="com.sparkjava:spark-core:2.5.4"
./gradlew clean test -PdependencyOverrides="org.springframework:spring-jdbc:4.3.4.RELEASE"
./gradlew clean test -PdependencyOverrides="org.springframework.restdocs:spring-restdocs-restassured:1.1.2.RELEASE"

这正是我所期待的。如果我复制并粘贴其中一个命令,它们就会完全按照我的要求执行。现在我不想打印这些命令但直接执行它们。但是,只要我从echo命令中删除xargs,它就无法正常工作。 "它没有工作"表示该属性未正确传递给gradle。

为了调试此问题,我尝试将| bash -x附加到我的管道中,该管道显示了该问题,但我不知道如何解决它。
附加这会产生以下输出作为第一行:

+ ./gradlew clean test $'-PdependencyOverrides=org.flywaydb:flyway-core:4.0.3\r'

我认为,问题在于bash由于某种原因,我不知道如何将参数放在引号中,并在$前加上它们。如果我完全按照此处打印的那样执行命令,则会发生同样的错误,就好像让xargs直接运行命令一样。

我需要更改哪些内容,以便在将echo添加到xargs命令时完全按照打印方式执行命令?

Herereport.json文件,如果有人想在本地重现,jq可以下载here

不需要Gradle来重现此问题,因为在没有gradlew文件的文件夹中执行命令只会产生:

+ ./gradlew clean test $'-PdependencyOverrides=org.flywaydb:flyway-core:4.0.3\r'
bash: line 1: ./gradlew: No such file or directory

仍然证明了这个问题。

我不确定究竟是什么问题,所以如果有更好的标题可以随意更改。

1 个答案:

答案 0 :(得分:3)

$'' is a valid way of quoting strings in Bash。它被使用是因为xtrace在必要时转义字符串以打印运行的确切命令。如果您尝试printf '%q\n' "$something",其中something包含特殊字符,如换行符,制表符,退格键等,则会得到相同类型的结果。

当您在某个编辑器/终端中查看输出时,

\r不会显示,但不会转义特殊字符。例如,如果您在行尾打开一个\r的文件,它只会在窗口底部显示[dos],表示行分隔符为\r\n(DOS / Windows标准而不是\n(* nix标准)。