sed:如何只提取第一次出现的价值

时间:2017-07-26 00:19:20

标签: regex bash unix sed

我的文件settings.inc.php包含以下内容:

<?php
define('_DB_SERVER_', 'mariadb');
define('_DB_NAME_', 'organic');
define('_DB_USER_', 'prestashop');
define('_DB_PASSWD_', 'prestashop');

我想将这些值提取到bash,因此我设法创建了以下命令:

sed -rn 's/^.*_DB_NAME_'\'', '\''(\w+)'\''\);/\1/p' settings.inc.php

这将返回organic,就像它应该的那样,但我想进一步改进它。让我们说我们会有这样的文件:

<?php
define('_DB_SERVER_', 'mariadb');
define('_DB_NAME_', 'organic1');
define('_DB_NAME_', 'organic2');
define('_DB_USER_', 'prestashop');
define('_DB_PASSWD_', 'prestashop');

在这个文件上使用上面的命令,我们得到:

organic1
organic2

问题是:我希望此命令始终只返回一个值,所以让我们说第一个。如果没有将结果输入第二个命令,我能实现吗?

4 个答案:

答案 0 :(得分:2)

也可以使用awk

$ awk -F "'" '$2=="_DB_NAME_"{print $4; exit}' settings.inc.php 
organic1
  • -F "'"使用单引号作为输入字段分隔符
  • $2=="_DB_NAME_"检查第二个字段是否为_DB_NAME_
  • print $4如果条件满足,请打印第4个字段
  • exit因为只需要第一场比赛

答案 1 :(得分:1)

使用GNU grep,你可以做到:

grep -m1 -Po "_DB_NAME_', '\K[^']+" settings.inc.php

grep参数是:

  • -m 1:在1场比赛后停止搜索
  • -P:打开Perl样式正则表达式(所以我们可以在这里使用\K
  • -o:仅打印与模式匹配的部分

模式的\K部分表示不包括作为匹配的一部分的所有内容,然后我们让模式的其余部分找到不是'的所有内容。

如果您想坚持sed,可以找到_DB_NAME_行,然后在找到后退出:

 sed -rn '/_DB_NAME/ {s/^.*_DB_NAME_'\'', '\''(\w+)'\''\);/\1/;p;q}' settings.inc.php

匹配_DB_NAME_,然后进入您的s ubstitution,p划线,然后q uits

答案 2 :(得分:0)

如果将替换命令后跟print打印到仅在pattern(包含)_DB_NAME_寻址的行上操作的命令块,则可以在第一次匹配/打印后退出:

$ sed -rn "/_DB_NAME_/ { s/.*'(\w+)'\);$/\1/p;q }" settings.inc.php
organic1

请注意q之后的p命令。

此外,您可以通过使用外部双引号并在末尾锚定来简化您的sed脚本。

答案 3 :(得分:0)

sed命令发送到head并选择第一行,如下所示:

sed -rn 's/^.*_DB_NAME_'\'', '\''(\w+)'\''\);/\1/p' settings.inc.php | head -1