2013-10-26 26 views
5

Ich benutze awk, um eine Zeichenkette mit einem bestimmten Trennzeichen in ein Array aufzuteilen. Jetzt möchte ich eine Operation für jedes Element des Arrays durchführen.bash awk split string in array

Ich bin in der Lage ein einzelnes Element wie folgt zu extrahieren:

#! /bin/bash 

b=12:34:56 
a=`echo $b | awk '{split($0,numbers,":"); print numbers[1]}'` 
echo $a 

ich so etwas wie dies tun will:

#! /bin/bash 

b=12:34:56 
`echo $b | awk '{split($0,numbers,":");}'` 
for(i=0;i<length(numbers);i++) 
{ 
    // perform some operation using numbers[i] 
} 

wie würde ich so etwas wie dies in der Bash Scripting tun?

Antwort

15

Sie brauchen nicht wirklich awk dafür, Bash kann einige String-Verarbeitung ganz von selbst tun.

Versuchen:

b=12:34:56 
for element in ${b//:/ } ; do 
    echo $element 
done 

Wenn Sie einen Zähler benötigen, ist es ziemlich trivial, dass hinzuzufügen.

Weitere Informationen darüber, was Sie direkt in bash tun können, finden Sie unter How do I do string manipulations in bash?.

6
b=12:34:56 
IFS=: 
set -- $b 
for i; do echo $i; done 

Dies enthält keine Bashismen, sondern funktioniert mit jedem SH.

+0

Beachten Sie, dass dies die Positionsargumente in '$ @' überschreibt, also müssen Sie sie vor dem Ausführen des Befehls 'set' nach Bedarf speichern. – chepner

+0

natürlich; Normalerweise setze ich komplexe Aufgaben in Funktionen, die ihren eigenen $ @ Kontext haben (das Abspeichern von "$ @" ist zu hässlich und fast unmöglich ohne Bashismen). – ensc

2

Der bash Lesebefehl kann eine Zeichenfolge in ein Array von selbst aufgeteilt:

IFS=: read -a numbers <<< "$b" 

Um zu sehen, dass es funktioniert:

echo "Hours: ${numbers[0]}" 
echo "Minutes: ${numbers[1]}" 
echo "Seconds: ${numbers[2]}" 

for val in "${numbers[@]}"; do 
    seconds=$((seconds * 60 + $val)) 
done 
1

Eine andere nette Art und Weise, nicht awk verwenden, aber build-in 'deklarieren':

b=12:34:56 

# USE IFS for splitting (and elements can have spaces in them) 
IFS=":" 
declare -a elements=($b) 
#show contents 
for ((i=0 ; i < ${#elements[@]}; i++)); do 
    echo "$i= ${elements[$i]}" 
done 
+0

Dies funktioniert nicht in allen Fällen; Wenn "b" nicht in Anführungszeichen gesetzt wird, wird die Erweiterung des Pfadnamens sowie die Worttrennung berücksichtigt. – chepner

11

Keine dieser Antworten verwendet awk (komisch). Mit awk können Sie tun so etwas wie:

echo 12:34:56 | awk '{split($0,numbers,":")} END {for(n in numbers){ print numbers[n] }}' 

ersetzt print numbers[n] mit was auch immer es ist, was Sie tun wollen.

+1

Sie benutzen 'awk' nicht, weil es keinen Grund gibt, ein externes Programm zu starten, um etwas zu tun, was' bash' bereits tun kann. – chepner

+10

Aber wenn die Frage ist, "wie man das in awk macht" und keine der Antworten "awk" beinhaltet, wird die Frage nicht wirklich beantwortet. Das Ergebnis ist, dass Google-Suchen ein nutzloses Ergebnis für jeden zurückgeben, der versucht herauszufinden, wie man genau dies in awk macht (was nützlich sein kann, weil sie bereits andere Dinge in awk tun und nur diese eine Sache hinzufügen wollen). –

+0

Ich kam in der Tat zu dieser Frage auf der Suche nach genau und speziell, wie es in awk zu tun. Diese Antwort war die einzige Antwort für mich. – Nick