使用grep / sed / awk从字符串中提取单词


12

我有一串

00:28:04 /usr/lib/jvm/jre/bin/java -DJDBC_CONNECTION_STRING= -Dspring.profiles.active=qa -XX:MaxPermSize=256

并要提取的词qa后面-Dspring.profiles.active

我将字符串保存在文件text.txt中只是为了对其进行演示。

当我做

grep -r -o "spring.profiles.active=" text.txt

结果是 spring.profiles.active=

这个词并不总是存在的qa,它可能是proddev

我想做的就是找到单词spring.profiles.active然后将其=提取出来。

我想使用shell脚本,因为我使用这个来配置服务器上的其他项目。

这可能吗,如果可以,我该怎么做。


我猜已经有关于此的元对话,但是这个问题完全不是Ubuntu特有的。为什么在这里而不是 unix.stackexchange.com
Tony Adams

@TonyAdams是的,这里已经间接涉及文本处理问题,无论如何事实上它们一直被认为是话题性的,并且从未关闭/迁移过;关于Ubuntu的特性,已经被讨论过多次,最近两次在这里,重复的在这里,一次。
kos 2015年

好问题!:D
ncomputers

Answers:


20

您可以grep与PCRE(-P)一起使用:

grep -Po 'spring.profiles.active=\K[^ ]+' <<<'.....string.....'
  • spring.profiles.active=将从字面上匹配此子字符串,\K将放弃匹配

  • [^ ]+将选择所需的部分,即之后的部分spring.profiles.active=,直到下一个空格

对于文件:

grep -Po 'spring.profiles.active=\K[^ ]+' file.txt

例:

% grep -Po 'spring.profiles.active=\K[^ ]+' <<<'00:28:04 /usr/lib/jvm/jre/bin/java -DJDBC_CONNECTION_STRING= -Dspring.profiles.active=qa -XX:MaxPermSize=256'
qa

sed 将采取类似的逻辑:

sed -r 's/.*spring.profiles.active=([^ ]+).*/\1/' <<<'.....string.....'

例:

% sed -r 's/.*spring.profiles.active=([^ ]+).*/\1/' <<<'00:28:04 /usr/lib/jvm/jre/bin/java -DJDBC_CONNECTION_STRING= -Dspring.profiles.active=qa -XX:MaxPermSize=256'
qa

处理错误:

在脚本中,您可能需要处理不匹配的情况,换句话说,原始字符串不包含spring.profiles.active=。在上面的sed示例中,您获得了整个原始字符串,这可能会产生问题:

% var="$(sed -r 's/.*spring.profiles.active=([^ ]+).*/\1/' <<<'00:28:04 /usr/lib/jvm/jre/bin/java -DJDBC_CONNECTION_STRING= -XX:MaxPermSize=256')"
% echo $var
00:28:04 /usr/lib/jvm/jre/bin/java -DJDBC_CONNECTION_STRING= -XX:MaxPermSize=256

如果您希望在没有匹配项的情况下获取空字符串,请将该-n选项添加到sed命令,并将该选项添加psed s命令,如下所示:

% var="$(sed -rn 's/.*spring.profiles.active=([^ ]+).*/\1/p' <<<'00:28:04 /usr/lib/jvm/jre/bin/java -DJDBC_CONNECTION_STRING= -XX:MaxPermSize=256')"
% echo $var

% var="$(sed -rn 's/.*spring.profiles.active=([^ ]+).*/\1/p' <<<'00:28:04 /usr/lib/jvm/jre/bin/java -DJDBC_CONNECTION_STRING= -Dspring.profiles.active=qa -XX:MaxPermSize=256')"
% echo $var
qa

然后,您可以测试$ var是否为空。


感谢@heemay,效果完美。现在我只需要编写脚本即可。我会标记为已回答
Gman 2015年

@heemay,您知道我该如何编写脚本。我将其保存在脚本中,当它运行时返回qa。我想将结果保存在名为env的变量中,然后将其与类似的东西进行比较。如果[env == qa]; 然后//做某事...否则做某事...
Gman

1
@Gman Yeah ..只需使用命令替换:如果输入是字符串而不是文件,则var="$(grep -Po 'spring.profiles.active=\K[^ ]+' file.txt)"替换为..那么您可以file.txt<<<'...string...'if [ "$var" = 'qa' ]; then do something; else do something; fi
heemayl 2015年

1

使用 awk

awk -F"-Dspring.profiles.active=" '{sub(/ .*/,"",$2);print $2}' <<<'your_string'

要么

awk -F"-Dspring.profiles.active=" '{sub(/ .*/,"",$2);print $2}' your_file

% awk -F"-Dspring.profiles.active=" '{sub(/ .*/,"",$2);print $2}' <<<'00:28:04 /usr/lib/jvm/jre/bin/java -DJDBC_CONNECTION_STRING= -Dspring.profiles.active=qa -XX:MaxPermSize=256'
qa

1

我将混合一个Perl:

<<<'string' perl -lane '$F[3]=~s/.*?=//;print($F[3])'
  • -l:启用自动行结束处理。它有两个单独的作用。首先,当与-n或-p一起使用时,它会自动砍掉$ /(输入记录分隔符)。其次,它将$ \(输出记录分隔符)分配为octnum的值,以便任何打印语句将重新添加该分隔符。如果省略octnum,则将$ \设置为$ /的当前值。
  • -a:当与-n或-p一起使用时,将打开自动分割模式。对@F数组的隐式split命令是由-n或-p生成的隐式while循环内的第一件事。
  • n:使Perl在您的程序周围假设以下循环,从而使其遍历文件名参数,如sed -n或awk:

    LINE:
      while (<>) {
          ...             # your program goes here
      }
  • -e:可用于输入程序的一行。
% <<<'00:28:04 /usr/lib/jvm/jre/bin/java -DJDBC_CONNECTION_STRING= -Dspring.profiles.active=qa -XX:MaxPermSize=256' perl -lane '$F[3]=~s/.*?=//;print($F[3])'
qa

原始正则表达式也可以这样使用:perl -nle '/spring.profiles.active=\K([^ ]+)/ && print $1' <<<'00:28:04 /usr/lib/jvm/jre/bin/java -DJDBC_CONNECTION_STRING= -Dspring.profiles.active=qa -XX:MaxPermSize=256'
Manwe
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.