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.



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[@]%%:*}")

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"


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
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.