Bash分割字符串

8
我有一个数组包含以下数据:
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'"

我想将它分为两个变量:$file$parameter
示例:
file="./path/path2/name.exe"
parameter="'word1 word2' 'name1,name2'"

我可以用awk来做这件事:
parameter=$(echo "${MY_ARR[1]}" | awk -F\' '{print $2 $4}')
file=$(echo "${MY_ARR[1]}" | awk -F\' '{print $1}')

这需要去除末尾空格,看起来太复杂了。

有更好的方法吗?

4个回答

15

看起来字段之间的分隔符是空格。因此,您可以使用cut命令来拆分它们:

file=$(echo "${MY_ARR[1]}" | cut -d' ' -f1)
parameter=$(echo "${MY_ARR[1]}" | cut -d' ' -f2-)
  • -f1 表示第一个参数。
  • -f2- 表示从第二个参数到最后的所有参数。

是的,我知道“cut”命令。我在第一次尝试时使用了它。我拒绝使用它,因为我担心如果有空格的话会错过第三和第四个字段...需要检查! - idobr

5
您可以使用read
$ read file parameter <<< ${MY_ARR[1]}
$ echo "$file"
./path/path2/name.exe
$ echo "$parameter"
'word1 word2' 'name3,name4,name5'

3
这是更好的解决方案,因为它不需要多个新进程来完成任务(一个用于命令替换,两个用于管道的两侧)。 - chepner

2

鉴于这个数组:

    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'"

让我们创建两个新数组 MY_FILES 和 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'"

如何访问每个文件:

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

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

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

    done

输出:

    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

如何访问每个参数:

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

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

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

    done

输出:

    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

由于${!MY_FILES[ [*]}会返回数组MY_FILES中的索引数字,因此您也可以使用相同的索引数字来访问其他数组。通过这种方式,您可以在同一个循环中访问多列数据。就像这样:

    ################
    #
    # 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
    )

输出:

                           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

除非我漏掉了什么,最简单和最便携的方法就是只使用两种扩展的变体。

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

解释

  • "${MY_ARR[0]%%' '*}" - 这将删除第一个空格和之后的所有内容,并返回剩余部分。
  • "${MY_ARR[0]#*' '}" - 这将��除第一个空格之前的所有内容,并返回剩余部分。

更详细的说明,请参见bash手册中的参数扩展部分。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接