从unix中的多行中提取文件名

问题描述 投票:1回答:2

我正在尝试提取由Java程序生成的文件名的名称。这个Java程序吐出多行,我确切地知道文件名的格式是什么。 Java程序吐出的信息文本如下:

ABCASJASLEKJASDFALDSF
Generated file  YANNANI-0008876_17.xml. 
TDSFALSFJLSDJF; 

我正在捕获变量中的输出,然后以下列格式应用sed运算符:

sed -n 's/.*\(YANNANI.\([[:digit:]]\).\([xml]\)*\)/\1/p'

结果集是:

YANNANI-0008876_17.xml.

但是,我的问题是想要提取文件名以停止在.xml。永远不应该提取最后一个点。

有没有办法用sed做到这一点?

sed
2个回答
0
投票

让我们来看看你的捕获组实际捕获的内容:

$ grep 'YANNANI.\([[:digit:]]\).\([xml]\)*' infile
Generated file  YANNANI-0008876_17.xml.

那可能不是你想要的:

  • \([[:digit:]]\)只捕获一个数字(并且它周围的捕获组没有做任何事情)
  • \([xml]\)*是“任何xml,0次或更多次”,所以它匹配空字符串(如上所述 - 或者根本不匹配!),xxxlllmxxxxxmmmmlxlxmxlmxlmxml ,. ..
  • 由于您在捕获组之后没有匹配任何内容,因此无法删除最后一个句点

更有意义的是:

  • 匹配“数字或下划线,0或更多”:[[:digit:]_]*
  • 匹配.xml,字面意思(逃离时期):\.xml
  • 在捕获组之后添加.*,确保匹配其余部分(在本例中为句点)

所以你要提取的字符串的正则表达式变成了

$ grep 'YANNANI.[[:digit:]_]*\.xml' infile
Generated file  YANNANI-0008876_17.xml.

并使用sed删除行上的所有其他内容,我们用.*\( ... \).*包围正则表达式:

$ sed -n 's/.*\(YANNANI.[[:digit:]_]*\.xml\).*/\1/p' infile
YANNANI-0008876_17.xml

这假设你真的是在.(任何角色)之后的YANNANI


0
投票

你可以调用sed两次:首先是打印然后是替换模式:

sed -n 's/.*\(YANNANI.\([[:digit:]]\).\([xml]\)*\)/\1/p' | sed 's/\.$//g'

最后一个sed将删除你的第一个sed提取的所有行末尾的所有最后一个.

或者您可以根据需要选择awk解决方案:

awk '/.*YANNANI.[0-9]+.[0-9]+.xml/{print substr($NF,1,length($NF)-1)}' 

这将打印与你的正则表达式匹配的所有行的最后一个字段(并使用substr截断它的最后一个字符)。

© www.soinside.com 2019 - 2024. All rights reserved.