如何使用`sed`匹配确切的字符串?但不是它的一部分。


8

我有一个输入文件FILE1.TXT如下。


11 id1  
12  
13 AGE = 20  
14 NAME = NAME1  
15  
16 id2  
17  
18 AGE = 30  
19 NAME = NAME2  
.  
.  
.  
110 idXYZ  
111  
112 AGE = AGEXYZ  
113 NAME = NAMEXYZ  
114  
115 idZZZ  
116

我想搜索属于特定ID的所有字段并获取NAME的值

我设法遍历每个Id,并根据需要为每个Id形成了以下命令。

sed -n '/11/,/14/p' FILE1.TXT | grep NAME | awk -F "= " '{print $2}'

这里的问题是,我得到了输出NAME1,除此之外,我还得到了NAMEXYZ

应该更改什么,以便我只获得NAME1而不获得NAMEXYZ

解决方法是,使用以下命令。

sed -n '/11/,/14/p' FILE1.TXT | grep NAME | awk -F "= " '{print $2}'|head -1

是否有任何“开关”或我缺少什么?

Answers:


3

如果知道要搜索的行号(如您的Q所示),请拧紧正则表达式,以免与不需要的行匹配。

例如,更改:

sed -n '/11/,/14/p' | grep NAME | awk -F "= " '{print $2}'

sed -n '/^11 /,/^14 /p' | grep NAME | awk -F "= " '{print $2}'

^将匹配行的开头和数量保证的具体行号都将匹配后的空间,你将不会处理不必要的块。


那会有所帮助。但是,我该如何搭配^(random no of spaces)11
Vinay 2014年

1
@VinayChalluru使用sed -n '/^\s*11 /,/^\s*14 /p'
Casey

1
sed -n '/^11 /,/^14 /p' | awk '/NAME/{print $NF}' 您尝试过此方法可能是短手?
Rahul Patil'3

@RahulPatil是的,有效。
Vinay 2014年

6

使用单词边界:

grep '\bNAME1\b'

将匹配NAME1,而不匹配NAME1XYZXYZNAME1

同样,

sed -n '/11\b/,/14\b/p'

将不匹配包含111和的行142


编辑:似乎输入文件中的数字实际上是行号。如果是这样,您可以简单地说:

sed '11,14!d'

得到想要的线。


NAME11和14行之间只有一个。因此,为什么sed要看111and 114?如何使其不介于111和之间114
Vinay 2014年

@VinayChalluru有关如何修改sed表达式的信息,请参见上面的答案。
devnull 2014年

我猜这回答了我的问题。让我尝试,让你知道。
Vinay 2014年

对于单词边界,grep带有-w标志?是不是?
Rahul Patil 2014年

1
@RahulPatil是的,对于上面的示例-w将是等效的。对于sed示例,-w则略有不同。
devnull 2014年

4

您可以使用AWK

awk 'NR>=13 && NR<=17 && /NAME/{print $NF}' infile

这将查找13至17之间的行,然后搜索“名称”,如果匹配,它将打印以下内容的最后一个单词 Name = LastWord


当我尝试这样做,我得到一个错误说,输入行数必须小于199.
维奈

@VinayChalluru您可以使用命令显示输出,请使用paste.ubuntu.com
Rahul Patil

道歉。我添加一个$之前,NR并导致错误。
Vinay 2014年

@VinayChalluru可以。很好,您尝试过/测试了每个ans并学习了一些新的知识。.:D
Rahul Patil 2014年

究竟。还有很多。:-)
Vinay 2014年

4

您不需要任何其他工具,sed就可以轻松地处理整个过程。

sed -nr '/11/,/14/{s/^.*NAME =\s*(\S*).*$/\1/p}' <$infile

对于输入的任何输入文件的第11行和第14行之间的每一行,这仅应为您提供短语“ NAME =”之后的第一行非空白字符sed


3

sed不是此工作的正确工具。使用awk,您可以在其中指定要查找的ID,并打印出现的下一个名称。

awk -v id="id2" '
    $NF == id {have_id = 1} 
    have_id && $0 ~ /NAME/ {print $NF; exit}
' filename

您能解释一下awk命令的第二行和第三行吗?
erik 2014年

0

通用版本不是基于行号而是ID参考

sed -n '1h;1!H;
$ {
  x
  s/.*/&\^J/
: clean
#  put your ID pattern here in place of id9
  s/.*\(id9 *\n.*\)id[0-9]\{1,\} *\n.*/\1/
  t clean
  s/.*NAME = \([^[:cntrl:]]*\)\n.*/\1/
  p
  }' YourFile
  1. 加载整个文件
  2. 干净部分不属于id组(递归)
  3. 只要在群组中取得NAME内容值
  4. 打印结果

0

您可以使用sed打印包含匹配模式的行,如下所示:

sed -n '/pattern/p'  Filename
  • -n-这些选项禁用此自动打印,并且sed仅在通过p命令明确告知时才产生输出。

  • p -打印

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.