如何在Bash中拆分带引号的字符串?

如何在Bash中拆分带引号的字符串?,bash,awk,split,Bash,Awk,Split,关于如何用给定的分隔符分割Bash脚本中的字符串,很少有人给出很好的答案 我的问题是我得到了一个带有空格分隔字符串的文件,该字符串可以被引用,例如 foo bar "foo bar baz" baz 我想将其分为4个值foo,bar,foo-bar-baz和baz 如何根据引号将这些输入拆分为Bash数组?默认情况下,Bashshell不提供多字符IFS分隔支持,但由于它是我们正在处理的文件,我们可以使用gnuawk及其对FPAT的支持来定义如何处理我们正在处理的每个单词 从GNU Awk手册

关于如何用给定的分隔符分割Bash脚本中的字符串,很少有人给出很好的答案

我的问题是我得到了一个带有空格分隔字符串的文件,该字符串可以被引用,例如

foo bar "foo bar baz" baz
我想将其分为4个值
foo
bar
foo-bar-baz
baz


如何根据引号将这些输入拆分为Bash数组?

默认情况下,
Bash
shell不提供多字符
IFS
分隔支持,但由于它是我们正在处理的文件,我们可以使用
gnuawk
及其对FPAT的支持来定义如何处理我们正在处理的每个单词

从GNU Awk手册页的

通常,当使用
FS
时,
gawk
将字段定义为记录中出现在每个字段分隔符之间的部分。换句话说,
FS
定义字段不是什么,而不是字段是什么。但是,有时您确实希望根据字段的性质来定义字段,而不是根据字段的性质来定义字段

后一部分是当我们需要使用
FPAT
时,为了满足您对空格分隔字符串和双引号内字符串的要求,我们定义了一个模式,如下所示,表示任何不是空格(或)但不包含双引号的内容

FPAT = "([^[:space:]]+)|("[^"]+")"
但要将其作为字符串写入
Awk
,需要对上面的双引号进行转义

awk 'BEGIN{FPAT = "([^[:space:]]+)|(\"[^\"]+\")"}{for(i=1;i<=NF;i++) print $i}' myFile
从这里开始,要存储在
bash
上下文中,所需的只是进程替换和
mapfile
命令

mapfile -t newArray < <(awk 'BEGIN{FPAT = "([^[:space:]]+)|(\"[^\"]+\")"}{for(i=1;i<=NF;i++) print $i}' myFile)
(或)明确地打印它

for item in "${newArray[@]}"; do
    printf '%s\n' "$item"
done

如果只有一个项目带有双引号,则可以使用此sed

sed 's/ /\n/g;h;s/[^"]*"\([^"]*\).*/"\1/;s/\n/ /g;x;G;s/\([^"]*\)"\([^"]*\)\("[^"]*\)\n\(".*\)/\1\4\3/' infile
如果是一个或多个,您可以使用此awk

awk -F'"' -vOFS='"' '{for (i=1;i<=NF;i++)if((i%2)==1){gsub(" ","\n",$i)}}1' infile

awk-F''''-vOFS='''''''''{for(i=1;这个问题有点简洁。是一行字符串还是字符串跨越多行?还有,到目前为止你做了什么来解决这个问题?你可以在
FPAT
中省略括号
()|()
,这正是我需要的-特别感谢你的精彩解释!
sed 's/ /\n/g;h;s/[^"]*"\([^"]*\).*/"\1/;s/\n/ /g;x;G;s/\([^"]*\)"\([^"]*\)\("[^"]*\)\n\(".*\)/\1\4\3/' infile
awk -F'"' -vOFS='"' '{for (i=1;i<=NF;i++)if((i%2)==1){gsub(" ","\n",$i)}}1' infile