假设有如下一行:
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'OST
和PGH"OST
。
我知道如果引号中不包含引号,我该如何获取值。下面是我的做法:
SED_COMMAND="s/^.*ENV\[['\"]\([^'\"]*\)['\"]\].*$/\1/"
echo $input | sed ${SED_COMMAND}
因此,上述内容对于input
存在foo bar ENV['PGHOST'] another bar
或foo 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,将整行翻译为仅要捕获的部分。