sed as grep + ignore#和match

时间:2010-05-31 07:53:21

标签: sed

我有以下文件示例

more somefile 

param=a b c d   e f g    z x w

# param=a b c d   e f g    z x w

我需要使用sed创建以下内容(如果可能,应该是一行):

  1. 在行首
  2. 中忽略#char
  3. 首先匹配参数字符串
  4. 第二次匹配“a b c d e f g z x w”(如grep -w)并在成功时给出退出状态
  5. 像......那样的东西。

    sed "/^ *#/b; /\<param\>/"  ....
    

2 个答案:

答案 0 :(得分:0)

第一个术语在开头删除带有'#'的行。 目前尚不清楚为什么你想要两个术语匹配参数和尾随材料(为什么不匹配?)。 目前尚不清楚是否要打印匹配的行。 并且不清楚您是否可以从sed获取退出状态,指示是否有任何行与模式匹配 - 您会被告知是否能够执行脚本并打开所有文件,但这就是全部。有了所有这些警告,那么:

sed -n '/^#/d;/param=a b c d   e f g    z x w/p' somefile

这会打印匹配的行,忽略(-n)那些不匹配的行。


如果'='符号周围有空格,您可以修改搜索模式以允许:

sed -n '/^#/d;/param *= *a b c d   e f g    z x w/p' somefile

目前尚不清楚“价值”部分内部的间距是否至关重要;如果不是,那么您可以使用适当的“*”(空格,空格,星号;标记编辑器再次努力工作)条款以允许可变空格。

但是,如果您想要类似grep的状态,则可能需要使用grep。正如我所指出的那样 - sed没有返回'找到模式'或'未找到模式'的状态,因为这不是它所关注的。


如果你真的希望sed做两个匹配,那么你必须进入分组操作,这些操作不再是单行脚本。

sed -n '/^#/d;/param/{
       /a b c d   e f g    z x w/p
       }' somefile

这说:

  • 删除以“#”开头的行。
  • 当您找到包含'param'的行时,
  • 为'a b c ...'行单独匹配,只打印结果(如果找到)。

注意:如上所述,第一个模式匹配也会找到'xyz = param'和'parameter = a b c';如果这不是您想要的,请适当修改模式。第二种模式也会发现'g h i a b c d ... x w';如果那不是你想要的,你必须适当地修改它。

我认为你最好用sed来删除注释和空行,然后使用你的grep序列来查找你的值。您必须使用GNU grep;其他计算机(Solaris,AIX,HP-UX等)上的POSIX标准版grep不支持-w选项。即使使用grep序列,您也无法区分如下行:

param=a b c d   e f g   z x w
a b c d   e f g   z x w=param

此外,这些都不允许在参数名称之前使用前导空格,并且它们都不允许使用制表符而不是空格。此外,必须有怀疑的余地,即使参数名称是固定的,价值也可能随时变化;将其转换为可用的shell脚本(调用sed或grep或两者)会增加要考虑的细节。


  • 搜索给定文件(参数3以后)以获取一般形式'name = value'的条目,其中name是参数1,value是参数2,忽略以'#'开头的注释行,并允许变量间距(但没有标签)围绕名称和等号;在值之前或之后必须没有数据。

这导致:

if [ $# -lt 3 ]; then echo "Usage: $0 name value file [...]" 1>&2; exit; fi
name=$1
value=$2
shift 2

sed -n -e '/^#/d' -e "/ *$name *= *$value *$/p" "$@"

现在,如果这个脚本被称为paramfinder,我可以写:

paramfinder param 'a b c d   e f g   z x w' somefile

我也可以写:

paramfinder param '.*a b c d  *e f g  *z x w.*' somefile

请注意,我已将正则表达式元字符传递给值中的sed脚本。

请注意,如果我通过它将会中断:

paramfinder passwordfile /etc/passwd somefile

那是因为“/ etc / passwd”中的斜杠会破坏正则表达式匹配。

根据您的实际要求(是家庭作业还是生产问题 - 以及它必须具备的健壮性),您可以考虑转移到Perl某处(或Python或您选择的其他类似脚本语言)。

答案 1 :(得分:0)

您可以使用嵌套花括号在AND中执行sed个条件:

sed -n '/\<param\>/ { /^[[:space:]]*#/ ! { /\<a \+b \+c \+d \+e \+f ... \>/ p}}'

这表示如果符合以下行匹配:

  • 它包含单词param
  • AND不会(!)以任何空格后的注释字符开头
  • AND有一个“单词”,由一个或多个空格分隔的字符序列组成

要测试是否成功,您需要查看结果是否为非空字符串:

if [[ -n $(sed ...) ]]