
Ich habe überall nach einer Lösung dafür gesucht, konnte aber keine finden.
Ich verwende , qstat -x
um eine große Zeichenfolge mit Jobinformationen zu übergeben. Die Ausgabe von qstat -x
erfolgt im XML-Format. Die gesuchten Teilzeichenfolgen befinden sich zwischen zwei expliziten Trennzeichen <Output_Path>
und </Output_Path>
. Hier ist ein Beispiel für einige der Ausgaben von qstat -x
, wobei vertrauliche Informationen zensiert wurden:
<Data><Job><Job_Id>4382.xxxxxxxx.xx.xxxxxxx</Job_Id><Job_Name>r053_x.xxMx.xxR_400k_neos2.pbs</Job_Name><Job_Owner>[email protected]</Job_Owner><job_state>H</job_state><queue>default</queue><server>xxxxxxxx.xx.xxxxxxx</server><Checkpoint>u</Checkpoint><ctime>1466396941</ctime><Error_Path>xxxxxxxx.xx.xxxxxxx:/data/xxxxxxxx/xxxxxxxxxxx/summer2016/relax/r053_x.xxMx.xxR_400k_neos2/r053_x.xxMx.xxR_400k_neos2.pbs.e4382</Error_Path><Hold_Types>u</Hold_Types><Join_Path>n</Join_Path><Keep_Files>n</Keep_Files><Mail_Points>a</Mail_Points><mtime>1466423857</mtime><Output_Path>xxxxxxxx.xx.xxxxxxx:/data/xxxxxxxx/xxxxxxxxxxx/summer2016/relax/r053_x.xxMx.xxR_400k_neos2/r053_x.xxMx.xxR_400k_neos2.pbs.o4382</Output_Path><Priority>0</Priority><qtime>1466396941</qtime><Rerunable>True</Rerunable><Resource_List><cput>9999:59:59</cput><nodect>1</nodect><nodes>1:ppn=12:gpus=1</nodes><walltime>2400:00:00</walltime></Resource_List><comment>Not Running: Not enough of the right type of nodes are available</comment><submit_args>r053_x.xxMx.xxR_400k_neos2.pbs</submit_args><fault_tolerant>False</fault_tolerant><job_radix>0</job_radix><submit_host>xxxxxxxx.xx.xxxxxxx</submit_host></Job><Job><Job_Id>4396.xxxxxxxx.xx.xxxxxxx</Job_Id><Job_Name>0R_20k_neos2.pbs</Job_Name><Job_Owner>[email protected]</Job_Owner><job_state>H</job_state><queue>default</queue><server>xxxxxxxx.xx.xxxxxxx</server><Checkpoint>u</Checkpoint><ctime>1466606895</ctime><Error_Path>xxxxxxxx.xx.xxxxxxx:/data/xxxxxxxx/xxxxxxxxxxx/summer2016/relax/r061_x.xxMx.xxR_20k_neos2/0R_20k_neos2.pbs.e4396</Error_Path><Hold_Types>u</Hold_Types><Join_Path>n</Join_Path><Keep_Files>n</Keep_Files><Mail_Points>a</Mail_Points><mtime>1466609370</mtime><Output_Path>xxxxxxxx.xx.xxxxxxx:/data/xxxxxxxx/xxxxxxxxxxx/summer2016/relax/r061_x.xxMx.xxR_20k_neos2/0R_20k_neos2.pbs.o4396</Output_Path><Priority>0</Priority>
Ich möchte alle Teilzeichenfolgen erhalten, die zwischen jeder Iteration von <Output_Path>
und liegen </Output_Path>
. Das heißt, wenn ich die Zeichenfolge
<Output_Path>xxxxxxxx.xx.xxxxxxx:/data/xxxxxxxx/xxxxxxxxxxx/summer2016/relax/r061_x.xxMx.xxR_20k_neos2/0R_20k_neos2.pbs.o4396</Output_Path><Output_Path>xxxxxxxx.xx.xxxxxxx:/data/xxxxxxxx/xxxxxxxxxxx/summer2016/relax/r053_x.xxMx.xxR_400k_neos2/r053_x.xxMx.xxR_400k_neos2.pbs.o4382</Output_Path>
Ich möchte einen Befehl, der zurückgibt
xxxxxxxx.xx.xxxxxxx:/data/xxxxxxxx/xxxxxxxxxxx/summer2016/relax/r061_x.xxMx.xxR_20k_neos2/0R_20k_neos2.pbs.o4396
xxxxxxxx.xx.xxxxxxx:/data/xxxxxxxx/xxxxxxxxxxx/summer2016/relax/r053_x.xxMx.xxR_400k_neos2/r053_x.xxMx.xxR_400k_neos2.pbs.o4382
oder
xxxxxxxx.xx.xxxxxxx:/data/xxxxxxxx/xxxxxxxxxxx/summer2016/relax/r061_x.xxMx.xxR_20k_neos2/0R_20k_neos2.pbs.o4396 xxxxxxxx.xx.xxxxxxx:/data/xxxxxxxx/xxxxxxxxxxx/summer2016/relax/r053_x.xxMx.xxR_400k_neos2/r053_x.xxMx.xxR_400k_neos2.pbs.o4382
Aber ich muss es ohne langsame for
Schleifen erledigen. Ich habe versucht, Variationen von awk
, grep
, und zu verwenden sed
, konnte aber nichts finden, was funktioniert hat.
Irgendwelche Ideen?
Antwort1
Versuchen Sie dann Folgendes:
xmlstarlet sel -t -v //Output_Path -nl data.xml
Antwort2
Wenn das Grep Ihres Systems PCRE unterstützt, könnten Sie vielleicht
$ echo 'aaa string1 bbb aaa string2 bbb aaa string3 bbb' |
grep -oP '(?<=(aaa|bbb) )\w*?(?= (aaa|bbb))'
string1
string2
string3
oder wenn Sie allgemeinere Mengen umgebender Leerzeichen verarbeiten müssen
$ echo 'aaa string1 bbb aaa string2 bbb aaa string3 bbb' |
grep -oP '(aaa|bbb)\s+\K\w*?(?=\s+(aaa|bbb))'
string1
string2
string3
Antwort3
Wenn Sie mit etwas Strukturiertem wie diesem zufrieden sind:
string1
string2
string3
Ich würde einfach die Trennzeichen durch eine neue Zeile ersetzen. So etwas sollte Ihnen nahe kommen:
sed "s/\(aaa\)\|\(bbb\)/\n/g" test.txt
Bearbeiten
Wie @clk unten anmerkt, kann meine erste Antwort doppelte Zeilenumbrüche ergeben. Ändern Sie sie in etwas wie:
sed "s/\(\s\)\?aaa\(\s\)\?/bbb/g" test.txt | sed "s/b*//g"
ergibt für mich:
string1 string2 string3
was auch beim Einspeisen genauso funktioniert, wie beispielsweise:
echo 'aaa string1 bbb aaa string2 bbb aaa string3 bbb' | sed "s/\(\s\)\?aaa\(\s\)\?/bbb/g" | sed "s/b*//g"
Nicht sehrhübschAntwort, aber schnell und einfach und gibt Ihnen das Format, nach dem Sie fragen.
Antwort4
Nur sed verwenden (mit -r
Flag für erweiterten regulären Ausdruck)
echo "aaa string1 bbb aaa string2 bbb aaa string3 bbb" | sed -r 's/(aaa|bbb) ?//g'
Kehrt zurück
string1 string2 string3
Sie haben auch diese Version mit tr und grep (mit -vE
):
echo "aaa string1 bbb aaa string2 bbb aaa string3 bbb" | tr ' ' '\n'| grep -vE '(aaa|bbb|^$)'
Kehrt zurück
string1
string2
string3
tr
ersetzt einfach das Leerzeichen durch ein neues Zeilenzeichen.
grep -vE
verwendet reguläre Ausdrücke („E“) und schließt die übereinstimmenden Zeilen („v“) aus.
Die dritte Version verwendet sed (ohne Flag) und grep (wie die letzte Version):
echo "aaa string1 bbb aaa string2 bbb aaa string3 bbb" | sed 's/\s/\n/g' | grep -vE '(aaa|bbb|^$)'
Macht so ziemlich genau dasselbe wie Version zwei, verwendet aber sed statt tr.
Bearbeiten: Außerdem wurde es ^$
in der Grep-Suchzeichenfolge hinzugefügt, um sicherzustellen, dass keine unerwünschten Zeilenumbrüche zurückgegeben werden.
Edit2: Ich sehe, Sie haben das OP geändert. Die obige Antwort bezieht sich auf die ursprüngliche Frage. Unten habe ich ein Skript erstellt, das Ihnen vielleicht weiterhelfen könnte: http://pastebin.com/uKWAGE0Y