Bash使用空格分隔值和双引号拆分字符串

Bash使用空格分隔值和双引号拆分字符串,bash,shell,Bash,Shell,在我的shell脚本中,有一个字符串保存所有参数 arg_str="arg1=ABC arg2=123 arg3= arg4=\"consecutive spaces and \\\"escaped quote\\\" shall be preserved within quotes\"" 我想按空格分割arg_str,但保留双引号中的任何内容。预期结果是: arg1=ABC arg2=123 arg3= arg4=consecutive spaces and \

在我的shell脚本中,有一个字符串保存所有参数

arg_str="arg1=ABC      arg2=123 arg3= arg4=\"consecutive      spaces and \\\"escaped quote\\\" shall be preserved within quotes\""
我想按空格分割arg_str,但保留双引号中的任何内容。预期结果是:

arg1=ABC
arg2=123
arg3=
arg4=consecutive      spaces and \"escaped quote\" shall be preserved within quotes
可以按双引号外的空格分割,但不能在双引号内保留连续空格

编辑 为什么我需要这个?我正在设计一个shell脚本来接受动态参数-arg name和value都是动态的,例如myscript.sh arg1=ABC arg2=123 arg3=arg4=连续空格和\escape quote\应保留在引号中。我不擅长狂欢。有人提到getopts,它似乎不适合动态args的情况。

如果您想给大多数Linux/Unix发行版上可用的perl一个机会,那么它是可行的:

arg_str="arg1=ABC      arg2=123 arg3= arg4=\"consecutive      spaces and \\\"escaped quote\\\" shall be preserved within quotes\""

perl -pe 's/"[^"\\]*(?:\\.[^"\\]*)*"(*SKIP)(*F)|\h+/$&\n/g' <<< "$arg_str"
正则表达式详细信息:

:比赛开场 [^\\]*:匹配一个非\ ?::启动一个非捕获组 \\:匹配a\ :匹配任意字符 [^\\]*:匹配一个非\ *:结束非捕获组。*表示重复此组0次或更多次 :比赛结束 *失败就像失败的否定断言,是?! *SKIP定义了一个点,在该点之后子模式失败时,不允许正则表达式引擎回溯该点 |:或 \h+:匹配1个或多个水平空白 如果您不想要perl,那么这里有一个基于gnu awk的解决方案:

awk -v FPAT='[^[:blank:]]*"[^\\\\"]*(\\\\.[^\\\\"]*)*"|[^[:blank:]]+' 
'{for (i=1; i<=NF; i++) print $i}' <<< "$arg_str"

我不知道您为什么要这样做,但这里有一个bash方法:

#!/bin/bash

#myscript.sh arg1=ABC arg2=123 arg3= arg4="consecutive      spaces and \"escaped quote\" shall be preserved within quotes"

for arg in "${@}"
do
    argname="${arg%%=*}"
    argvalue="${arg##*=}"
    parameters[$argname]="$argvalue"
done

printf "\n" 
echo  "${parameters[arg2]}"

问候

使用字符串进行此操作从根本上讲是不正确的。好吧,你为什么要把它放在这样一根绳子里?还有getopts。这能回答你的问题吗?我建议不要鼓励OP去解决设计问题。我无意鼓励/阻止任何设计模式。我所看到的问题是,需要使用引号和转义引号拆分输入,而这些引号和转义引号需要在引号之外的水平空格上拆分。@OP:在阅读您编辑的问题之后,该字符串似乎是作为脚本的命令行参数出现的。如果是这样,为什么不直接使用printf'\n'$@并检查输出。@anubhava是的,我用它来解析命令行动态参数。我不熟悉shell脚本,不确定它是否是一个好的解决方案。您的perl和printf版本运行良好,解决了我的问题。谢谢
arg1=ABC
arg2=123
arg3=
arg4="consecutive      spaces and \"escaped quote\" shall be preserved within quotes"
#!/bin/bash

#myscript.sh arg1=ABC arg2=123 arg3= arg4="consecutive      spaces and \"escaped quote\" shall be preserved within quotes"

for arg in "${@}"
do
    argname="${arg%%=*}"
    argvalue="${arg##*=}"
    parameters[$argname]="$argvalue"
done

printf "\n" 
echo  "${parameters[arg2]}"