【问题标题】:extracting a word from a string in unix从unix中的字符串中提取一个单词
【发布时间】:2012-11-30 07:17:35
【问题描述】:

我想从 unix 中的字符串中提取模式之前的单词。我怎样才能做到这一点?

例如: 说字符串是 “sv_z = sample.scr” 在字符串中我必须搜索“.scr”。如果在字符串中找到,我必须提取整个单词。在这个例子中,输出应该是 样本.scr。到达单词的分隔符可以是空格、双引号或等于。

这里还有几个例子:

sv_z=sample.scr
sv_z=urhk_dbCall("sample.scr")
sv_z="sample.scr"

这是我的预期输出:

sample.scr
sample.scr
sample.scr

【问题讨论】:

    标签: unix sed awk


    【解决方案1】:

    这是使用grep的一种方式:

    grep -o '[^ "=]*\.scr' file
    

    解释:

    • -o 标志与模式完全匹配。
    • [ ... ] 是一个字符类。如果克拉 (^) 用作该类的第一个字符,则表示该类的否定,它实际上意味着“没有以下字符”。
    • * 表示匹配最后一个字符,零次或任意次数。

    编辑:

    或者,如果您需要更严格的要求,则需要 Perl-regex 和 positive lookahead。在下面的示例中,这将确保匹配后跟双引号、空格或行尾。此外,您可以将星号 (*) 更改为加号 (+),表示匹配一次或多次。所以这会过滤掉类似的东西:.scr。但从您的示例输入 究竟 并不清楚您在此处寻找什么。祝你好运。

    grep -oP '[^ "=]*\.scr(?=("| |$))' file
    

    【讨论】:

    • 你需要转义那个“.”或者它会匹配“unscramble”中的“unscr”。如果 OP 不想自己匹配“.scr”,您也可能需要将 * 更改为 +。我还认为可能需要一些终止 RE(可能类似于 ([ "=]|$) 但你需要以某种方式从打印的表达式中排除它)所以它匹配“.scr”但不匹配“.scrabble”但 OP 没有还没有真正告诉我们。
    • @EdMorton:谢谢 Ed,那里有一些有效的 cmets,尤其是逃生。不知何故错过了。添加了更严格的前瞻。
    【解决方案2】:

    在这个 awk 脚本中,我使用变量“d”来包含允许的分隔符列表,以保存在脚本中重复它们多次:

    $ cat file
    sv_z=sample.scr
    sv_z=urhk_dbCall("sample.scr")
    sv_z="sample.scr"
    sv_z="unscrambled"
    sv_z="sample.scrambled"
    
    $ awk -v d=' "=' 'match($0,"["d"][^"d"]+\.scr(["d"]|$)") { $0=substr($0,RSTART,RLENGTH); gsub("["d"]",""); print NR, $0 }' file
    1 sample.scr
    2 sample.scr
    3 sample.scr
    

    与发布的 grep -o 解决方案比较:

    $ grep -n -o '[^ "=]*.scr' file
    1:sample.scr
    2:sample.scr
    3:sample.scr
    4:unscr
    5:sample.scr
    

    注意 grep 输出中可能不需要的最后 2 行。

    【讨论】:

    • 此命令似乎有效。但在某些情况下,此命令仍然失败。例如 exebatch mrbx4004 $B2K_SESSION_ID scrFilename.scr $ListFile4 $OutputReport $RipFile 从上面的字符串中我需要提取名称 scrFilename.scr,这似乎不起作用。请帮忙。
    • 对我来说很好。字符串之前/之后是否有制表符而不是空格,或者您的行以 control-Ms 或其他内容结尾?我发布的代码将满足您发布的要求。
    • 感谢您的回复。错误来自我这边。但还有一件事,我需要提取与给定模式匹配的所有字符串,即使该模式在同一行中不止一次出现。例如,在下面的代码中,我需要同时提取 ubixres.scrCheckSact.scr。这可能吗? sv_q = urhk_TBAF_SetKeyScript("bafe3012.optionblk.key-f2|ubixres.scr||CheckSact.scr")
    • 是的,您需要将 match() 调用放在一个循环中,并在每次迭代中修改 $0 以去除匹配的前面部分。
    【解决方案3】:

    另一种解决方案:

     awk -F= 'NR==1{print $2}{FS="\""}NR>1{print $2}' file
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-09-10
      • 2015-05-08
      • 2019-05-21
      • 1970-01-01
      • 2016-12-27
      • 2021-03-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多