【问题标题】:Split Bash String That Contain '&&'拆分包含 '&&' 的 Bash 字符串
【发布时间】:2019-06-03 07:28:08
【问题描述】:

我有一个这样的 bash 脚本:

#!/bin/bash

params="path=/me & you/folder/file.json&&user=Bob"
splitParams=(${params//&&/ })

for i in "${!splitParams[@]}"
do
    echo "$i: ${splitParams[i]}"
done

它产生:

0: path=/me
1: &
2: you/folder/file.json
3: user=Bob

但是当我在 shell 中输入 em 时:

➜  params="path=/me & you/folder/file.json&&user=Bob"
➜  splitParams=(${params//&&/ })
➜  echo $splitParams
path=/me & you/folder/file.json user=Bob

我希望脚本的输出就像我在 shell 中键入时一样:

0: path=/me & you/folder/file.json
1: user=Bob

【问题讨论】:

  • splitParams=(${params//&&/ }) 行首先将所有&& 替换为一个空格,然后将每个空格处的字符串标记/拆分为一个数组。在脚本和命令行中都会发生同样的情况。直接打印这个数组(就像你在命令行上做的那样)将在一行上用一个空格连接所有元素。当然,循环遍历数组(就像在脚本中所做的那样)会将每个元素打印在单独的行上。
  • 脚本的循环可以像这样在命令行中输入:for i in "${!splitParams[@]}"; do echo "$i: ${splitParams[$i]}"; done。对了,脚本有错误,应该是"$i: ${splitParams[$i]}"而不是"$i: ${splitParams[i]}"

标签: string bash split ampersand


【解决方案1】:

您可以为此目的使用 awk,但请记住 splitParams 不能在 awk 之外访问。我们将使用 awk 的 split 函数:

split([要处理的字符串], [结果数组], [分隔符])

#!/bin/bash
params="path=/me & you/folder/file.json && user=Bob"
awk -F: '{split($0, splitParams, "&&"); print splitParams[1] "\n"splitParams[2]}' <<< $params

输出:

 path=/me & you/folder/file.json
  user=Bob

【讨论】:

    【解决方案2】:

    echo $splitParams 只打印第一个元素。使用declare -p 准确查看数组中的内容:

    $ declare -p splitParams
    declare -a splitParams=([0]="path=/me" [1]="&" [2]="you/folder/file.json" [3]="user=Bob")
    

    那么现在你如何在&amp;&amp; 处拆分字符串,但又不会让空格搞砸?好吧,依靠shell来做是容易出错的。当输入字符串已经包含空格时,将&amp;&amp; 更改为空格并在空格上拆分会遇到麻烦。

    更好的方法是将分隔符更改为换行符。然后,不要使用array=($string)$string 分开,而是使用readarray,这样空格就不会触发拆分,只有换行符。

    $ readarray -t splitParams < <(sed 's/&&/\n/g' <<< "$params")
    $ declare -p splitParams
    declare -a splitParams=([0]="path=/me & you/folder/file.json" [1]="user=Bob")
    

    【讨论】:

      【解决方案3】:

      你可以这样使用:

      params="path=/me & you/folder/file.json&&user=Bob"
      while IFS=  read -r -d $'\0'
      do
        splitParams+=("$REPLY")
      done < <(echo "${params}" | awk -F'&&' '{ for (i=1;i<=NF;i++) printf("%s\0",$i); }')
      
      for i in "${!splitParams[@]}"
      do
          echo "$i: ${splitParams[i]}"
      done
      

      输出:

      0: path=/me & you/folder/file.json
      1: user=Bob
      

      【讨论】:

      • 实际上我的代码中没有使用任何 GNU AWK 扩展。并且兼容 UNIX awk --traditional
      【解决方案4】:
      grep -oP '(?<=^|&&).*?(?=&&|$)' <<< "path=/me & you/folder/file.json&&user=Bob"
      

      打印:

      path=/me & you/folder/file.json
      user=Bob
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-01-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-13
        相关资源
        最近更新 更多