Wie ordne ich die Ausgabe eines Befehls einem Array zu?

77

Ich muss die Ergebnisse von a grepeinem Array zuweisen ... zum Beispiel

grep -n "search term" file.txt | sed 's/:.*//'

Dies führte zu einer Reihe von Zeilen mit Zeilennummern, in denen der Suchbegriff gefunden wurde.

1
3
12
19

Was ist der einfachste Weg, sie einem Bash-Array zuzuweisen? Wenn ich sie einfach einer Variablen zuordne, werden sie zu einer durch Leerzeichen getrennten Zeichenfolge.

Decke Katze
quelle
Siehe diese Frage
beerbajay
Durch Leerzeichen getrennte Zeichenfolgen können in Bash leicht durchlaufen werden.
Shiplu Mokaddim
ooh ... hätte gründlicher suchen sollen. Vielen Dank.
Decke Katze
Abgesehen davon ist es eine übliche Antipattern-Verwendung grep, um die Zeilennummern von etwas abzurufen und sie schließlich an ein Tool weiterzugeben, das über eine eigene Regex-Unterstützung verfügt. Dann kann es die gleichen Zeilen wie grepgefunden finden, ohne den Umweg zu machen, die Zeilennummern der Übereinstimmungen herauszufinden.
Tripleee

Antworten:

135

Um die Ausgabe eines Befehls einem Array zuzuweisen, müssen Sie eine Befehlsersetzung innerhalb einer Arrayzuweisung verwenden. Für einen allgemeinen Befehl commandsieht dies so aus:

arr=( $(command) )

Im Beispiel des OP würde dies lauten:

arr=($(grep -n "search term" file.txt | sed 's/:.*//'))

Das Innere $()führt den Befehl aus, während das Äußere ()bewirkt, dass die Ausgabe ein Array ist. Das Problem dabei ist, dass es nicht funktioniert, wenn die Ausgabe des Befehls Leerzeichen enthält. Um damit umzugehen, können Sie einstellen , IFSauf \n.

IFS=$'\n'
arr=($(grep -n "search term" file.txt | sed 's/:.*//'))
unset IFS

Sie können die Notwendigkeit von sed auch verringern, indem Sie für jedes Element des Arrays eine Erweiterung durchführen:

arr=($(grep -n "search term" file.txt))
arr=("${arr[@]%%:*}")
Jordanm
quelle
4
plus eins für die Behandlung des Falls mit Leerzeichen in den Elementen. Genau das, wonach ich gesucht habe.
Vladislavs Dovgalecs
1
Das IFS-Zeug ist großartig! Ich habe stundenlang gesucht!
Magnusarinell
für mich funktionierte es nur ohne äußere Klammern dvmList=`grep -RohP '(?<=oramds:).+\.dvm' myFolder`
tuxErrante
@bastaPasta Das ist keine Array-Zuweisung. Die Array-Zuweisung hat bei Ihnen möglicherweise nicht funktioniert, wenn Sie keine Shell verwendet haben, die Arrays unterstützt.
Jordanm
Sie haben Recht, ich habe sh anstelle von bash verwendet, aber es funktioniert gut in einem for
tuxErrante
10

Durch Leerzeichen getrennte Zeichenfolgen können in Bash leicht durchlaufen werden.

# save the ouput
output=$(grep -n "search term" file.txt | sed 's/:.*//')

# iterating by for.
for x in $output; do echo $x; done;

# awk
echo $output | awk '{for(i=1;i<=NF;i++) print $i;}'

# convert to an array
ar=($output)
echo ${ar[3]} # echos 4th element

Wenn Sie an Speicherplatz im Dateinamen denken, verwenden Sie find . -printf "\"%p\"\n"

Shiplu Mokaddim
quelle
5
Aber kaputt für Dateien mit Leerzeichen.
Jordanm
@ Jordanm verwendenfind . -printf "\"%p\"\n"
Shiplu Mokaddim
@ ShipluMokaddim, das funktioniert nicht. for x in $outputMit einem solchen findBefehl wird eine Datei mit dem Namen two wordsals ein Wert "twound ein anderer Wert durchlaufen words".
Charles Duffy vor
@ShipluMokaddim, ... dasselbe gilt, wenn Sie ar=( $output )mit outputauf diese Weise zugewiesen verwenden, da die Ergebnisse der Parametererweiterung und Befehlssubstitution nicht die Analysephase zum Entfernen von Anführungszeichen durchlaufen.
Charles Duffy vor