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

3

有一些问题没有很好的答案,关于如何在Bash脚本中按照给定的分隔符拆分字符串。

我的问题是,我有一个用空格分隔的字符串文件,其中可能有引号,例如:

foo bar "foo bar baz" baz

我希望将其拆分为4个值foo, bar, foo bar bazbaz。如何通过保留引号将这些输入拆分为Bash数组?

1
这个问题有点简洁。它只是一行字符串还是跨越多行的字符串?此外,你已经做了什么来解决这个问题? - sjsam
2个回答

4
默认情况下,bash shell不支持多字符IFS分隔符,但由于我们处理的是文件,因此可以使用GNU Awk并利用其支持FPAT的功能来定义如何处理每个单词。
从GNU Awk手册中,在通过内容定义字段章节中找到以下内容:
引用:
通常,使用FS时,gawk将字段定义为记录中每个字段分隔符之间出现的部分。换句话说,FS定义了字段不是什么,而不是字段是什么。但是,有时您确实想要根据它们的内容定义字段,而不是根据它们不是什么定义字段。
后一部分是我们需要使用FPAT的时候,对于您需要处理的以空格分隔的字符串和双引号内的字符串,我们定义一个模式如下,这意味着不是空格(或)包含在双引号中但不是双引号的任何内容。
FPAT = "([^[:space:]]+)|("[^"]+")"

但是如果要将其作为字符串写入 Awk 中,则需要对上面的双引号进行转义。

awk 'BEGIN{FPAT = "([^[:space:]]+)|(\"[^\"]+\")"}{for(i=1;i<=NF;i++) print $i}' myFile

这将会把你输入的每个单词分别打印在不同的行中,如下所示,
foo
bar
"foo bar baz"
baz

从这里开始,要将所有内容存储在 bash 上下文中,您只需要使用进程替换和 mapfile 命令。

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

然后您可以将数组打印为

declare -p newArray 

(或者)显式地打印它。
for item in "${newArray[@]}"; do
    printf '%s\n' "$item"
done

在编程中,将以下内容从英语翻译成中文。仅返回已翻译的文本:您可以省略“FPAT”中的括号(<pattern1>)|(<pattern2>)。 - RomanPerekhrest
1
正是我需要的 - 特别感谢您提供的出色解释! - muffel

0

如果只有一个带双引号的项目,您可以使用这个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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接