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



我正在使用 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

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

(^([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命令被完全忽略,因为sed的输出没有被grep读取。你可以指示 grep 从文件和标准输入中读取:

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

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

默认情况下,当grep从多个文件中读取时,它将在每个匹配项之前加上该匹配项的来源文件名。这也是你在我上面的例子中看到的——两个输入,一个x.txt,另一个-又名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:%sn", f, $0
getline                  # simulate the "-A 1" from grep
printf "%s:%sn", f, $0
}' *.txt

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

此外,awk不包括GNU grep通过--colour选项提供的任何花哨的终端依赖着色。

最新更新