如何获取单引号或双引号之间的值?

如何获取单引号或双引号之间的值?

假设有如下一行:

foo bar ENV['PGHOST'] another bar

我想获取PGHOST旁边方括号内的值ENV。我假设该行只有一个这样的情况。因此,这:foo bar ENV['PGHOST'] another bar ENV['FOO'] and foo不是输入。

"但是,该行可能会以而不是 的形式出现',如下所示:

foo bar ENV["PGHOST"] another bar

换句话说,我想要获取的值可能用双引号或单引号括起来。

不仅如此,实际值可能包含双引号或单引号。如果它用单引号括起来,那么它可以包含双引号。如果它用双引号括起来,那么它可以包含单引号。因此,这两行是有效的预期输入:

foo bar ENV["PGH'OST"] another bar
foo bar ENV['PGH"OST'] another bar

如果我得到像上面那样的行,则结果应该分别是PGH'OSTPGH"OST

我知道如果引号中不包含引号,我该如何获取值。下面是我的做法:

SED_COMMAND="s/^.*ENV\[['\"]\([^'\"]*\)['\"]\].*$/\1/"
echo $input | sed ${SED_COMMAND}

因此,上述内容对于input存在foo bar ENV['PGHOST'] another barfoo bar ENV["PGHOST"] another bar举例来说都可以正常工作。

但它对 不起作用foo bar ENV['PG"HOST'] another bar,对 也不起作用foo bar ENV["PG'HOST"] another bar

任何帮助都将不胜感激。请注意,我不必解决问题sed。任何其他建议都可以接受。

更新。请注意,我可能有这样的输入:

foo bar ENV['PGHOST'] another bar "what a world" I 'live' in
foo bar ENV["PGHOST"] another bar "what a world" I 'live' in

ENV即双引号和/或单引号可能存在​​于我想要提取的键之外的输入部分。

更新其他有效输入示例:

foo bar ENV['PGHOST'] another bar in NEW['YORK'] to visit

它可以是有效的输入。我需要得到PGHOST

这也是有效的:

foo bar ENV["PGH'OST"] another bar ["baz"]

应该返回PGH'OST

答案1

以下更谨慎的 Bash 脚本首先删除第一次出现 ENV[ 之后的字符及其之前的所有内容,然后删除第一次出现 ] 之前的字符及其之后的所有内容。如果您还有其他情况导致此操作无法按预期运行,请告知。

x="foo bar ENV['PGHOST'] another bar in NEW['YORK'] to visit"; 
x=${x#*ENV[?}; x=${x%%?]*}; echo $x

以下版本将从名为“输入”的文件中读取并将结果写入名为“输出”的文件中。

cd ~/Desktop; 
while IFS= read -r x; 
do x=${x#*ENV[?}; echo ${x%%?]*} >> output;  
done < input 

如果“输入”包含:

foo bar ENV['PGHOST'] another bar
foo bar ENV["PGHOST"] another bar
foo bar ENV["PGH'OST"] another bar
foo bar ENV['PGH"OST'] another bar
foo bar ENV['PGHOST'] another bar "what a world" I 'live' in
foo bar ENV["PGHOST"] another bar "what a world" I 'live' in
foo bar ENV['PGHOST'] another bar in NEW['YORK'] to visit
foo bar ENV["PGH'OST"] another bar ["baz"]

那么以下内容将被写入“输出”:

PGHOST
PGHOST
PGH'OST
PGH"OST
PGHOST
PGHOST
PGHOST
PGH'OST

答案2

以下 Bash 脚本应删除:

1 - 直到第一个 [ 以及其后的一个字符的所有内容

2 - 第一个] 以及它之后的所有内容和它之前的一个章节。

x="foo bar ENV['PGHOST'] another bar"; x=${x#*[?}; x=${x%%?]*}; echo $x 

第一次尝试未能按预期显示,直到我缩进 4 个空格。

现在改为删除第一个 ] 之后的所有内容。

我认为这应该适用于您现有的所有案例,但您可能希望添加更多案例。

答案3

$ SED_COMMAND="s/^.*ENV\[\(.\)\(.*\)\1\].*$/\2/"

$ cat input
foo bar ENV['PGHOST'] another bar
foo bar ENV['PGHO"ST'] another bar
foo bar ENV["PGHO'ST"] another bar
foo bar ENV["PGHOST"] another bar

foo bar ENV['PGHOST'] another bar "what a world" I 'live' in
foo bar ENV["PGHOST"] another bar "what a world" I 'live' in

foo bar ENV['PGHOST'] another bar in NEW['YORK'] to visit
foo bar ENV["PGH'OST"] another bar ["baz"]


$ cat input | sed ${SED_COMMAND}
PGHOST
PGHO"ST
PGHO'ST
PGHOST

PGHOST
PGHOST

PGHOST'] another bar in NEW['YORK
PGH'OST"] another bar ["baz

几乎可以解决你所有愚蠢的问题。除了最后两个,你需要 perl 才能完成,因为sed 没有非贪婪功能或者删除方括号内的引号并使用 [:alpha:] 或 \w。我所做的更改是假设界定要捕获的单词的引号(' 或 ")直接跟在打开的方括号后面[,然后使用,以捕获 ' 或 ",并将其用作 \2 反向引用的结束分隔符。然后,像您所做的那样使用 sed,将整行翻译为仅要捕获的部分。

相关内容