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

时间:2017-12-21 17:49:34

标签: sed

我试图提取由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做到这一点?

2 个答案:

答案 0 :(得分: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

答案 1 :(得分: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截断它的最后一个字符)。