2013-01-31 10 views
8

Ich habe folgende Daten in Array:Bash geteilt Zeichenfolge

MY_ARR[0]="./path/path2/name.exe 'word1 word2' 'name1,name2'" 
MY_ARR[1]="./path/path2/name.exe 'word1 word2' 'name3,name4,name5'" 
MY_ARR[2]=".name.exe 'word1 word2'" 
MY_ARR[3]="name.exe" 
MY_ARR[4]="./path/path2/name.exe 'word1 word2' 'name1'" 
MY_ARR[5]="./path/path2/name.exe 'word1 word2' 'name.exe, name4.exe, name5.exe'" 

ich es in zwei Variablen teilen möchten: $file und $parameter.

Beispiel:

file="./path/path2/name.exe" 
parameter="'word1 word2' 'name1,name2'" 

Ich kann es mit awk:

parameter=$(echo "${MY_ARR[1]}" | awk -F\' '{print $2 $4}') 
file=$(echo "${MY_ARR[1]}" | awk -F\' '{print $1}') 

Dies muss Leerzeichen entfernen, und sieht zu kompliziert.

Gibt es einen besseren Weg, es zu tun?

Antwort

15

Es sieht so aus, als wäre das Trennzeichen zwischen den Feldern ein Leerzeichen. Daher können Sie cut sie zu spalten verwenden:

file=$(echo "${MY_ARR[1]}" | cut -d' ' -f1) 
parameter=$(echo "${MY_ARR[1]}" | cut -d' ' -f2-) 
  • -f1 bedeutet den ersten Parameter.
  • -f2- bedeutet alles aus dem zweiten Parameter.
+0

ja, ich weiß über Schnitt. Ich habe es bei meinem ersten Versuch benutzt. Ich habe mich geweigert, es zu benutzen, weil ich Angst hatte, das dritte und vierte Spiel zu verpassen, wenn die Felder leer sind. – idobr

5

können Sie verwenden read:

$ read file parameter <<< ${MY_ARR[1]} 
$ echo "$file" 
./path/path2/name.exe 
$ echo "$parameter" 
'word1 word2' 'name3,name4,name5' 
+3

Dies ist die bessere Lösung, da zur Ausführung der Aufgabe nicht mehrere neue Prozesse erforderlich sind (einer für die Befehlsersetzung, zwei für beide Seiten der Pipeline). – chepner

2

Vor diesem Array:

MY_ARR[0]="./path/path2/name.exe 'word1 word2' 'name1,name2'" 
    MY_ARR[1]="./path/path2/name.exe 'word1 word2' 'name3,name4,name5'" 
    MY_ARR[2]=".name.exe    'word1 word2'" 
    MY_ARR[3]="name.exe" 
    MY_ARR[4]="./path/path2/name.exe 'word1 word2' 'name1'" 
    MY_ARR[5]="./path/path2/name.exe 'word1 word2' 'name.exe, name4.exe, name5.exe'" 

Lets 2 neue Arrays MY_FILES machen und MY_PARAMETERS

for MY_ARR_INDEX in ${!MY_ARR[*]} ; do 

     ###### 
     # Set the current file in new array. 

       MY_FILES[ ${MY_ARR_INDEX} ]=${MY_ARR[ ${MY_ARR_INDEX} ]// *} 

     ###### 
     # Set the current parameters in new array 

     MY_PARAMETERS[ ${MY_ARR_INDEX} ]=${MY_ARR[ ${MY_ARR_INDEX} ]#* } 

     ###### 
     # Show the user whats happening 
     # (from here until done is just printing info.) 

     printf "MY_FILES[ ${MY_ARR_INDEX} ]=\"%s\" ; MY_PARAMETERS[ ${MY_ARR_INDEX} ]=\"%s\"\n" \ 
     \ 
      "${MY_ARR[ ${MY_ARR_INDEX} ]// *}" "${MY_ARR[ ${MY_ARR_INDEX} ]#* }" 

    done 


    MY_FILES[ 0 ]="./path/path2/name.exe" ; MY_PARAMETERS[ 0 ]="'word1 word2' 'name1,name2'" 
    MY_FILES[ 1 ]="./path/path2/name.exe" ; MY_PARAMETERS[ 1 ]="'word1 word2' 'name3,name4,name5'" 
    MY_FILES[ 2 ]=".name.exe" ; MY_PARAMETERS[ 2 ]="   'word1 word2'" 
    MY_FILES[ 3 ]="name.exe" ; MY_PARAMETERS[ 3 ]="name.exe" 
    MY_FILES[ 4 ]="./path/path2/name.exe" ; MY_PARAMETERS[ 4 ]="'word1 word2' 'name1'" 
    MY_FILES[ 5 ]="./path/path2/name.exe" ; MY_PARAMETERS[ 5 ]="'word1 word2' 'name.exe, name4.exe, name5.exe'" 

Wie jede Datei zuzugreifen:

for MY_ARR_INDEX in ${!MY_FILES[*]} ; do 

     CUR_FILE=${MY_FILES[ ${MY_ARR_INDEX} ] } 

     echo "# Do something with this file: ${CUR_FILE}" 

    done 

Ausgang:

Do something with this file: ./path/path2/name.exe 
    Do something with this file: ./path/path2/name.exe 
    Do something with this file: .name.exe 
    Do something with this file: name.exe 
    Do something with this file: ./path/path2/name.exe 
    Do something with this file: ./path/path2/name.exe 

Wie jeden Parameter zuzugreifen:

for MY_ARR_INDEX in ${!MY_PARAMETERS[*]} ; do 

     CUR_FILE=${MY_FILES[ ${MY_ARR_INDEX} ]} 

     echo "# Do something with this parameter: ${CUR_FILE}" 

    done 

Ausgang: {! MY_FILES [[*]}

Do something with this parameter: ./path/path2/name.exe 
    Do something with this parameter: ./path/path2/name.exe 
    Do something with this parameter: .name.exe 
    Do something with this parameter: name.exe 
    Do something with this parameter: ./path/path2/name.exe 
    Do something with this parameter: ./path/path2/name.exe 

Da $ Ergebnisse in der Index NUMBERS des Arrays MY_FILES Sie können auch die gleichen Indexnummern verwenden, um auf die anderen Arrays zuzugreifen. In t Auf diese Weise können Sie auf mehrere Datenspalten in derselben Schleife zugreifen. Wie so:

################ 
    # 
    # Print each file and matching parameter(s) 
    # 
    ################ 

    # Set a printf format string so we can print all things nicely. 

    MY_PRINTF_FORMAT="# %25s %s\n" 

    ################ 
    # 
    # Print the column headings and use index numbers 
    # 
    #  to print adjacent array elements. 
    # 
    ################ 
    (

      printf "${MY_PRINTF_FORMAT}" "FILE" "PARAMETERS" "----" "----------" 

     for MY_ARR_INDEX in ${!MY_FILES[*]} ; do 

      printf "${MY_PRINTF_FORMAT}" "${MY_FILES[ ${MY_ARR_INDEX} ]}" "${MY_PARAMETERS[ ${MY_ARR_INDEX} ]}" 

     done 
    ) 

Ausgang:

      FILE PARAMETERS 
          ---- ---------- 
      ./path/path2/name.exe 'word1 word2' 'name1,name2' 
      ./path/path2/name.exe 'word1 word2' 'name3,name4,name5' 
         .name.exe    'word1 word2' 
         name.exe name.exe 
      ./path/path2/name.exe 'word1 word2' 'name1' 
      ./path/path2/name.exe 'word1 word2' 'name.exe, name4.exe, name5.exe' 
1

Es sei denn, ich etwas fehle, einfachste und tragbare Art und Weise wäre, nur für diese zwei Varianten Expansion zu verwenden.

file="${MY_ARR[0]%%' '*}" 
parameter="${MY_ARR[0]#*' '}" 

Erklärung

  • "${MY_ARR[0]%%' '*}" - Dies entfernt den ersten Raum und alles, nachdem er und kehrt verbleibende Teil
  • "${MY_ARR[0]#*' '}" - Dies alles bis zum ersten Platz entfernt, und gibt die restlichen Teil

Für eine ausführlichere Erklärung, siehe die Parameter Expansion Abschnitt der bash man Seite

Verwandte Themen