it-swarm.com.de

Teilen Sie eine Zeichenfolge (in einer Variablen gespeichert) in mehrere Wörter, verwenden Sie Leerzeichen, nicht jedoch die Leerzeichen in doppelten Anführungszeichen

Ich versuche, ein für mich kompliziertes Skript zu schreiben, dessen Ziel es ist, Folgendes zu tun. Ich habe einen String, der so aussieht:

2012 2013 "multiple words"

Mein Ziel ist es, jedes auf ein Array zu setzen, das durch Leerzeichen getrennt ist, jedoch nur für einzelne Word-Übereinstimmungen, nicht jedoch für solche, die in doppelte Anführungszeichen gesetzt sind. Diese sollten als ein Wort betrachtet werden. Meine Idee war also, dies in zwei Schritten zu tun. Stimmen Sie zuerst die Wörter ab, die Vielfache sind, entfernen Sie die Wörter aus der Zeichenfolge und dann in einer anderen Iteration, die durch Leerzeichen getrennt ist.
Leider kann ich keine Hilfe finden, wie man nur das Spiel echo. Bisher habe ich folgendes:

array=$(echo $tags | sed -nE 's/"(.+)"/\1/p')

Dies würde jedoch zu (unter OS X) führen:

2012 2013 multiple words

Erwartetes Ergebnis:

array[1]="2012"
array[2]="2013"
array[3]="multiple words"

Wie würde ich bei so einem Problem vorgehen? 

Vielen Dank.

19
Zettt

eval ist böse, aber dies kann einer der Fälle sein, in denen es praktisch ist

str='2012 2013 "multiple words"'
eval x=($str)
echo ${x[2]}
multiple words

Oder mit neueren Versionen von bash (getestet auf 4.3)

s='2012 2013 "multiple words"'
declare -a 'a=('"$s"')'
printf "%s\n" "${a[@]}"
2012
2013
multiple words
20
iruvar
$ grep -Eo '"[^"]*"|[^" ]*' <<< '2012 2013 "multiple words"'
2012
2013
"multiple words"

Das heißt, print only die passenden Zeichenfolgen

  1. ein Zitat, gefolgt von einer beliebigen Zahl (auch Null), gefolgt von einem Zitat oder
  2. eine Reihe von Zeichen, die kein Zitat oder Leerzeichen enthalten.

Natürlich behandelt dies nicht komplizierte Fälle wie Anführungszeichen, die mehrere Zeilen umfassen, oder Escape-Anführungszeichen (mit doppelten Anführungszeichen wie SQL oder Backslash wie der Shell).

4
l0b0

Sie können direkt tun:

arr=(2012 2013 "multiple words")

echo ${#arr[@]} # gives 3
echo ${arr[2]} # gives "multiple words"

BEARBEITEN: Nicht sicher, ob es dem OP hilft, aber das Folgen wird auch funktionieren

str='2012 2013 "multiple\ words"'
read -a arr <<< $str
echo ${#arr[@]} # gives 3
echo ${arr[2]} # gives "multiple words"
2
anubhava

Folgendes wird das gewünschte Ergebnis erzeugen:

tags='2012 2013 "multiple words"'
IFS=$'\n'; array=($(echo $tags | egrep -o '"[^"]*"|\S+'))

ergebnis in ZSH:

echo ${array[1]} # 2012
echo ${array[2]} # 2013
echo ${array[3]} # "multiple words"

ergebnis in BASH:

echo ${array[0]} # 2012
echo ${array[1]} # 2013
echo ${array[2]} # "multiple words"

funktioniert in OSX.

1
zekus

Hier ist ein kleines Python-Skript, um die durch Leerzeichen getrennten CSV-Werte unter Berücksichtigung der in Anführungszeichen gesetzten Felder zu analysieren:

$ python -c '
import csv, fileinput
for line in csv.reader(fileinput.input(), delimiter=" "):
   for Word in line:
      print Word
' test.csv
2012
2013
multiple words

Da dies das Fileinput-Modul verwendet, funktioniert es auch in einer Pipeline (oder einem String in einer Variablen):

$ str='2012 2013 "multiple words"'
$ echo $str | python -c '
import csv, fileinput
for line in csv.reader(fileinput.input(), delimiter=" "):
   for Word in line:
      print Word
' 
2012
2013
multiple words
0
dawg