2016-12-04 9 views
1

Ich habe eine Pipeline von Bash-Befehle, die wie folgt aussieht:Unexpected bash Verhalten zitiert

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 

Die Ausgabe dieses Befehls lautet:

./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" 

Das ist genau das, was ich erwarte. Wenn ich einen dieser Befehle kopiere und einfüge, tun sie genau das, was ich möchte. Jetzt möchte ich diese Befehle nicht drucken, sondern sie direkt ausführen. Sobald ich jedoch den Befehl echo aus dem Befehl xargs entferne, funktioniert es nicht. "Es funktioniert nicht" bedeutet, dass die Eigenschaft nicht korrekt an Großbuchstaben übergeben wurde.

Um dieses Problem zu debuggen, habe ich versucht, an meine Pipeline | bash -x anzuhängen, die das Problem offenbarte, aber ich weiß nicht, wie man es löst.
Anfügen Dies ergibt die folgende Ausgabe als erste Zeile:

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

Ich gehe davon aus, das Problem ist, dass bash aus irgendeinem Grunde weiß ich nicht, die Argumente in Anführungszeichen setzt und prepends sie mit $. Wenn ich den Befehl genau so ausführe, wie er hier gedruckt wird, tritt derselbe Fehler auf, als ob ich den Befehl xargs direkt ausführen lasse.

Was muss ich ändern, damit die Befehle genau so ausgeführt werden, wie sie gedruckt werden, wenn ich den Befehl echo zum Befehl xargs hinzufüge?

Here ist die report.json Datei, wenn jemand dies möchte lokal reproduzieren und jq können here heruntergeladen werden.

Gradle ist nicht erforderlich, dieses Problem zu reproduzieren, wie es ohne gradlew Datei den Befehl in einem Ordner Ausführung nur ergibt:

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

, die immer noch das Problem demonstriert.

Ich bin nicht sicher, was das genaue Problem ist, also wenn es einen besseren Titel gibt, fühlen Sie sich frei, es zu ändern.

+1

beachten Sie das '\ r' Zeichen. Sie sollten einen dos2unix in Ihrer Eingabedatei versuchen. –

+0

Sie haben Recht! Wenn Sie das '\ r' aus dem Befehl entfernen, kann es ordnungsgemäß ausgeführt werden. –

+2

die "setzt die Argumente in Anführungszeichen und fügt ihnen $ voran". ist eine Debugging-Ausgabe von der Shell. (ksh macht das gleiche).Die Shell muss alle dbl-quotierten Strings, Variablen, cmd-Substitution output, die in einfachen Anführungszeichen stehen, normalisieren. Dies ist nur eine Möglichkeit, anzuzeigen, was das Ergebnis von Variablen, cmd-sub, single und dbl in Anführungszeichen ist. r 'ist mir auch verdächtig ;-). Viel Glück. – shellter

Antwort

3

$'' is a valid way of quoting strings in Bash. Es wird verwendet, da xtrace Zeichenketten bei Bedarf ausgibt, um den exakten Befehl zu drucken, der ausgeführt wurde. Sie erhalten die gleiche Art von Ergebnis, wenn Sie zu printf '%q\n' "$something" versuchen, wo something wie Newline Sonderzeichen enthält, Tab, Backspace usw.

\r wird nicht sichtbar sein, wenn Sie am Ausgang in einigen Editor/Terminal suchen, die nicht der Fall ist Sonderzeichen entkommen. Wenn Sie beispielsweise am Ende der Zeile eine Datei mit \r öffnen, wird am unteren Rand des Fensters einfach [dos] angezeigt, um anzuzeigen, dass das Zeilentrennzeichen \r\n (DOS/Windows-Standard) statt \n (* nix-Standard) ist.