仅在第一行匹配特定模式时才如何打印文件内容?


11

我正在编写脚本,我想检查文件的第一行是否匹配特定的模式,然后将其打印出来。我该如何实现?

如何检查图案?有没有一种方法可以检查模式并根据输出执行某些操作。

编辑:请看一下这个问题:https : //stackoverflow.com/questions/5536018/how-to-get-match-regex-pattern-using-awk-from-file

我想要这样的东西,但是他们都没有为我工作。我基本上想检查第一行是否匹配正则表达式模式,并根据该结果打印文件行。


1
您期望的输出是什么?您正在寻找什么模式?你都尝试了些什么?
tachomi

@tachomi编辑,请看一下
Mathew

Answers:


17

您可以使用ed

ed -s infile <<\IN 2>/dev/null
1s/PATTERN/&/
,p
q
IN

这里的关键是要尝试更换PATTERN1st与自己一致。ed如果找不到指定的模式,则会出错,因此,p(打印整个文件)仅在1s/PATTERN/&/成功的情况下执行。

或搭配sed

sed -n '1{
/PATTERN/!q
}
p' infile

qUITS如果第一行不(!)匹配PATTERN,否则它prints所有行。
或者,正如Toby Speight所指出的那样,使用GNU sed

sed '1{/PATTERN/!Q}' infile

Q与相同,q但不打印图案空间。


您可以Q代替qGNU sed或dq(便携式)之前,以免分别要求-nflag和pcommand:sed '1{/PATTERN/!Q}' infilesed -e '1{' -e '/PATTERN/!{' -e 'd' -e 'q' -e '}' -e '}' infile
Toby Speight 2015年

d重新启动命令周期总是让我失望!:-|
Toby Speight

使用GNU sed,第一个sed命令会抱怨sed: -e expression #1, char 10: extra characters after command(由于p),但是ed和最后一个sed建议都可以正常工作。
Skippy le Grand Gourou

注意:与其他答案相比,此答案提供的解决方案的优点是可以将其应用于管道。
Skippy le Grand Gourou

1
@SkippyleGrandGourou-您尝试将其变成单线而不用分号分隔命令-这是正确的方法sed -n '1{/PATTERN/!q};p'
don_crissti

15

使用POSIX工具箱:

{ head -n 1 | grep pattern && cat; } <file

1
{double} <甜。
mikeserv

@mikeserv:我打算用它来防止新人感到困惑,但是Stephane编辑的内容更加清晰。
cuonglm

8
 awk '/pattern/{print FILENAME}; {nextfile}' ./*.txt

txt在当前目录中打印未隐藏文件的名称,该文件的第一行将扩展的正则表达式pattern那些awk支持的补充nextfile匹配。

如果要打印整个文件内容而不是打印文件名,则可以执行以下操作:

 awk 'FNR == 1 && ! /pattern/ {nextfile}; {print}' ./*.txt

这是有效的,因为它仅运行一个命令,但awk不是转储文件内容(对于大文件)的最有效命令,您可以通过执行以下操作来获得更好的性能:

 awk '/pattern/{printf "%s\0", FILENAME}; {nextfile}' ./*.txt |
   xargs -r0 cat

也就是说,仅用于awk打印匹配(以0分隔)并依赖于cat转储其内容的文件列表。


6

如果您正在编写Shell脚本,则可以这样

for file in ./*; do head -n 1 "$file" | grep -q 'PATTERN' && cat "$file"; done

或者,在Perl中:

perl -Tlne '$f = /PATTERN/ if $. == 1; print if $f; $. = 0 if eof' ./*

@StéphaneChazelas:也许比分配给close ARGV更加习惯$.
cuonglm

@terdon Yours看起来像是代码高尔夫球,全部都在一行中,变量名周围没有括号,也不鼓励使用整洁的结构。当我发布信息时,您的美元符号丢失了,那不是教bash的方法。我认为这些因素来自您似乎也拥有的perl背景,因此您将被原谅!;)

@guest您好,欢迎访问该网站!我将您的答案转换为评论,因为只有在回答实际问题时才能发布答案。这不是经典意义上的论坛,我们只希望在这里进行纯粹的问答。您可能需要看一下帮助中心浏览以更好地了解该站点。就是说,我的背景实际上是生物学的,是的,我的代码还远远不够干净:)但是,我看不到括号在这里有什么帮助,引号已经保护了变量。有什么会打破括号所要保护的呢?
terdon

@来宾啊,对不起,忘了你不能发表评论。随时来聊天进行解释,我敢肯定我会学到一些东西。
terdon

5

Oldschool,只需将您的句子翻译成标准命令即可:

for file in *; do
    if head -n 1 "${file}" | grep -q 'PATTERN'; then
        cat "${file}"
    fi
done

学习bash是一个好的开始。如果您只需要快速解决方案,请尝试使用sed,awk或perl答案。两者都很不错,但是它们是您需要(并且可能想要)学习的自己的语言。

这是一个非常简单的示例,因此,如果您想了解更多信息,也可以尝试使用ruby,php,js(例如,在nodejs中)或其他允许文件访问的语言进行相同的尝试。即使是C / C ++或Java,也应该可以轻松完成一项小任务。


1
除了您使用代替之外,这与我的基本相同。if/else[ ] &&
terdon
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.