Bash用双引号将空格分隔的值分割为字符串

时间:2019-12-16 14:40:28

标签: 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 \"escaped quote\" shall be preserved within quotes

This answer可以按双引号之外的空格分隔,但不能保留双引号内的连续空格。

编辑 为什么我需要这个?我正在设计一个shell脚本来接受动态参数-arg名称和值都是动态的,例如myscript.sh arg1=ABC arg2=123 arg3= arg4="consecutive spaces and \"escaped quote\" shall be preserved within quotes"。我不擅长bash。有人提到getopts,似乎不适合动态参数的情况。

2 个答案:

答案 0 :(得分:1)

如果您想给perl(在大多数Linux / Unix发行版中都可以使用),那么可以这样做:

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"

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

RegEx Demo

RegEx详细信息:

  • ":比赛开始"
  • [^"\\]*:匹配不是"而不是\的字符
  • (?::启动一个非捕获组
    • \\:匹配一个\
    • .:匹配任意字符
    • [^"\\]*:匹配不是"而不是\的字符
  • )*:结束非捕获组。 *表示该组重复0次或更多次
  • ":比赛闭幕"
  • (*FAIL)的行为类似于失败的否定断言,并且是(?!)的同义词
  • (*SKIP)定义了一个点,当子模式稍后失败时,不允许正则表达式引擎回溯
  • |:或
  • \h+:匹配1个或多个水平空白

如果您不想使用perl,则可以使用以下基于gnu awk的解决方案:

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

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

答案 1 :(得分:0)

我不知道您为什么要这样做,但这是一种简便的方法:

#!/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]}"

致谢!

相关问题