【问题标题】:Bash split stringbash 拆分字符串
【发布时间】:2013-01-15 18:02:05
【问题描述】:

我在数组中有以下数据:

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}')

这需要去掉尾随空格,看起来很复杂。

有没有更好的方法?

【问题讨论】:

    标签: string bash awk split cut


    【解决方案1】:

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

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

    说明

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

    有关更详细的说明,请参阅 bash 手册页的 Parameter Expansion 部分

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

      • 是的,我知道剪切。我第一次尝试时使用它。我拒绝使用它,因为如果是空格,我害怕错过第三和第四场......需要检查!
      【解决方案3】:

      给定这个数组:

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

      让我们创建 2 个新数组 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 的索引号为 NUMBERS,因此您也可以使用相同的索引号访问其他数组。这样,您可以在同一个循环中访问多列数据.像这样:

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

      【讨论】:

        【解决方案4】:

        你可以使用read:

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

        【讨论】:

        • 这是更好的解决方案,因为它不需要多个新进程来完成任务(一个用于命令替换,两个用于管道的任一侧)。
        猜你喜欢
        • 1970-01-01
        • 2011-10-30
        • 2021-10-23
        • 2016-05-30
        • 2013-08-08
        • 1970-01-01
        • 1970-01-01
        • 2019-06-03
        • 2011-11-26
        相关资源
        最近更新 更多