2015-07-08 15 views
5

Ich habe eine Datei mit Befehlszeilenargumenten, die ich an ein anderes Skript übergeben möchte. Diese Datei enthält Elemente wie "param 1" param2 param3. Geben Sie die Datei mit den Argumenten test.tmp und der Skriptdatei script.sh ein.Befehlszeilenargument von Dateiinhalt mit Zitat

Wenn ich tun:

script.sh -p `cat test.tmp` -other_params 1 2 3 

Die script.sh erhält nach p:

  1. "param
  2. 1"
  3. param2
  4. param3

Aber ich möchte:

  1. param 1
  2. param2
  3. param3

Jede Idee?

Kleine Genauigkeit: angenommen, dass script.sh nicht änderbar ist. Die Lösung muss in der Shell stattfinden.

+0

In einer idealen Welt 'test.tmp' sollte in NUL- gespeichert werden Begrenzte Form - die * einzige * Syntax, die alle möglichen Werte speichern kann, ohne das Parsen zu erfordern. (Sicheres Parsen von Shell-Quoting ohne Sicherheitsrisiken einzugehen, z. B. Expansionen zuzulassen, ist überraschend schwierig - es sei denn, Sie übergeben den Job an "xargs", aber selbst dann ist sein Verhalten nicht _quite_ kompatibel mit tatsächlichen bash Parsing). Wenn Sie die Gelegenheit bekommen, die Leute, die 'script.sh' geschrieben haben, dazu zu ermutigen, dies zu überdenken, würde ich Ihnen vorschlagen, dies zu tun. –

+0

Der von Tom vorgeschlagene 'mapfile -t'-Ansatz ist ebenfalls eine vernünftige Methode, * wenn * Sie eine Garantie haben, dass Ihre Argumente niemals literale Zeilenumbrüche enthalten müssen. –

+0

BTW, siehe http://mywiki.wooledge.org/BashFAQ/050 und seine Links (dh zu den WordSplitting und Argumente Seiten) für einige Verständnis um * warum * das Standardverhalten passiert. –

Antwort

6

NAHME:test.tmp Bedürfnisse mit diesem Ansatz einen Parameter pro Zeile enthalten.

Sie können xargs verwenden, um mit einem Zeilenvorschub Trennzeichen:

cat test.tmp | xargs -d '\n' script.sh -p 
+0

Das funktioniert perfekt. Ich habe Kontrolle über test.tmp, aber nicht über script.sh. Danke –

+1

Ein Vorbehalt: Wenn Sie eine wirklich lange Argumentliste haben, wird 'xargs'' script.sh' mehrere Male mit verschiedenen Teilmengen dieser Liste ausführen, anstatt direkt zu scheitern. In einigen Fällen kann dies unerwünscht sein. –

2

Ihre Datei wie folgt auslegen:

param 1 
param2 
param3 

es dann so in ein Array lesen:

mapfile -t params < file 

dann Ihr Skript wie folgt aufrufen:

script.sh -p "${params[@]}" -other_params 1 2 3 

Der Vorteil Dieser Ansatz verwendet nur integrierte bash-Befehle und benötigt keine eval.

alles in einer Zeile zu tun, können Sie verwenden:

mapfile -t params < file && script.sh -p "${params[@]}" -other_params 1 2 3 

heißt && verwenden Sie den zweiten Befehl, wenn der erste gelang auszuführen.

1

Mit grep mit Perl regex:

IFS=$'\n'; ./script.sh -p $(grep -woP '((?<=")[^"]*(?="))|([\S]+)' test.tmp) 

Beispiel:

Skript.sh:

#!/bin/bash 
echo "$1" 
echo "$2" 
echo "$3" 
echo "$4" 
... 

Ausgang:

-p 
param 1 
param2 
param3 
... 

Hinweis: Es wird die IFS der aktuellen Shell ändern (wo Sie diese Befehle ausgeführt werden).

+0

Dies funktioniert nicht für mein Problem. Wenn der Wert von $ (...) erhöht wird, wird der erste Parameter "param" und der zweite Parameter ist "1". Wenn der erste Parameter 'param 1' sein soll –

+0

Dieser Ansatz sendet die (quotierte) grep Ausgabe als zweiten Parameter an 'script.sh', während OP erwartet, dass 'param2' und' param3' als separate Argumente gesendet werden. –

+0

@EugeniuRosca Ich habe es bearbeitet, denke, das wird funktionieren .. – Jahid

6

Sie den Befehl in eval wickeln können:

eval "script.sh -p `cat test.tmp` -other_params 1 2 3" 

$ cat test.tmp 
"params 1" param2 param3 

$ cat script.sh 
#!/bin/bash 
echo $1 
echo $2 
echo $3 
echo $4 
echo $5 
echo $6 

$ eval "./script.sh -p `cat test.tmp` other_params 1 2 3" 
-p 
params 1 
param2 
param3 
other_params 
1 
+2

Eww. Bitte tun Sie das nicht, es sei denn, Sie vertrauen dem Inhalt von "test.tmp". Wenn es, sagen wir, $ (rm -rf.) 'enthält, sind Sie in einem schlechten Tag. –

+0

Ja, das ist im Allgemeinen ein guter Punkt, aber das OP sagte, dass er in diesem Fall die Kontrolle über "test.tmp" hat, also besteht keine Gefahr. –

+0

Es ist eine Sache, das Format einer Datei zu steuern, eine andere Sache, um den Inhalt zu kontrollieren. Wenn ich das Skript besitze, das 'foo.txt' schreibt, aber die Ausgabe dieses Skripts basierend auf Eingaben geschrieben wird, die zur Laufzeit angegeben werden, kann meine Ausgabe, solange ich nicht sehr vorsichtig bin, nicht als nicht bösartig eingestuft werden. –