Unix文本处理 - 如何从结果中删除部分文件名?

时间:2018-03-12 01:46:12

标签: unix sed grep text-processing

我正在使用grep和sed命令搜索文本文件,我还希望在结果之前显示文件名。但是,我试图在显示文件名时删除部分文件名。

文件名的格式如下:aja_EPL_1999_03_01.txt

我希望只有没有开头字母且没有.txt扩展名的日期。

我一直在寻找答案,似乎可以使用sed或grep命令通过使用这样的东西来向前看和向后并在_和.txt之间提取:

(?<=_)\d+(?=\.)

但我必须做错事,因为它对我没有用,我可能还要添加一些东西,这样它就不会只提取第一个数字,而是提取整个日期。提前谢谢。

编辑:添加我以前用过的工作命令。我想在开始时需要做什么命令?

sed '/^$/d' *.txt | grep -P '(^([A-ZÖÄÜÕŠŽ].*)?[Pp][Aa][Ll]{2}.*[^\.]$)' *.txt --colour -A 1

结果如下:

aja_EPL_1999_03_02.txt:PALLILENNUD : korraga üritavad ümbermaailmalendu kaks meeskonda

期望的输出是:

1999_03_02:PALLILENNUD : korraga üritavad ümbermaailmalendu kaks meeskonda

1 个答案:

答案 0 :(得分:0)

首先,您可能想要考虑正则表达式。虽然你说的那个有用,但我想知道它是否可以简化。你告诉我们:

(^([A-ZÖÄÜÕŠŽ].*)?[Pp][Aa][Ll]{2}.*[^\.]$)

在我看来,这似乎是为了匹配以不区分大小写的“PALL”开头的行,可能之前是以大写字母开头的任意数量的其他字符,并且这些行不能以反斜杠或一个点。所以有效行可能是以下任何一行:

PALLILENNUD : korraga üritavad etc etc
Õlu on kena. Do I have appalling speling?
Peeter Pall is a limnologist at EMU!

如果你想稍微缩小这个描述范围并提供一些应该匹配或跳过的行的例子,我们可能会做得更好。例如,您的外括号可能是不必要的。

现在,让我们澄清你的做什么。

sed '/^$/d' *.txt

这会将所有.txt文件作为输入流读取,删除所有空行,并将输出打印到stdout。

grep -P 'regex' *.txt --otheroptions

这会读取所有.txt文件,并打印与regex匹配的所有行。 它不读取标准输入。

所以..在你现在使用的命令行中,你的sed命令完全被忽略,因为grep没有读取sed的输出。您可以指示grep从两个文件和stdin中读取:

$ echo "hello" > x.txt
$ echo "world" | grep "o" x.txt -
x.txt:hello
(standard input):world

但这不是你正在做的事情。

默认情况下,当grep从多个文件中读取时,它将在每次匹配之前与发起匹配的文件的名称相对应。这也是你在我上面的例子中看到的 - 两个输入,一个x.txt和另一个- a.k.a. stdin,用它们提供的匹配的冒号分隔。

虽然grep确实包含了最小的过滤功能(使用-o,或者GNU grep的\K具有可选的Perl兼容RE),但它不提供任何格式化选项文件名。由于您可以对grep的输出执行任何操作,因此您只能解析您已获得的输出,或者使用其他工具。

解析很容易,如果你的文件名是可预测的结构,因为它们似乎来自你提供的两个例子。

为此,我们可以忽略这些行包含文件和数据。出于过滤目的,它们是,它遵循模式。看起来你想从每一行的开头剥离所有字符,直到不包括第一个数字。你可以通过sed:

进行管道来做到这一点
sed 's/^[^0-9]*//'

或者你可以通过使用grep的最小过滤从第一个数字开始返回每个匹配来实现相同的效果:

grep -o '[0-9].*'

如果这种管道不适合您,您可能希望将整个grep替换为awk中结合了功能的内容:

$ awk '
    /[\.]$/ {next}             # skip lines ending in backslash or dot
    /^([A-ZÖÄÜÕŠŽ].*)?PALL/ {  # lines to match
      f=FILENAME
      sub(/^[^0-9]*/,"",f)     # strip unwanted part of filename, like sed
      printf "%s:%s\n", f, $0
      getline                  # simulate the "-A 1" from grep
      printf "%s:%s\n", f, $0
    }' *.txt

请注意,我没有对此进行测试,因为我没有您的数据可供使用。

此外,awk不包括GNU grep通过--colour选项提供的任何奇特的终端相关着色。