如何检查文件的第一行是否包含特定字符串?

Z E*_*Nir 7 shell grep read

我需要写一个shell脚本,找到并打印的所有文件,其中以开头的目录:#include。现在,我知道如何使用以下命令检查文件中是否存在字符串:

for f in `ls`; do
    if grep -q 'MyString' $f; then:
        #DO SOMETHING
    fi
Run Code Online (Sandbox Code Playgroud)

但是如何将其应用于第一行?我想可能会创建第一行的变量并检查它是否以 开头#include,但我不确定如何执行此操作。我尝试了该read命令,但无法读入变量。

我想听听解决这个问题的其他方法;也许awk?无论如何,请记住,我需要检查第一行是否以 开头#include,而不是它是否包含该字符串。这就是我发现这些问题的原因:仅当第一行与特定模式匹配时,如何打印文件内容? /sf/ask/387521291/ 他们并没有完全帮助。

ImH*_*ere 16

很容易检查第一行是否以#includein (GNU and AT&T) sed开头:

sed -n '1{/^#include/p};q'   file
Run Code Online (Sandbox Code Playgroud)

或简化(和 POSIX 兼容):

sed -n '/^#include/p;q'   file
Run Code Online (Sandbox Code Playgroud)

仅当文件包含#include在第一行时才会有输出。那只需要读取第一行就可以进行检查,所以会非常快。

因此,所有文件(带有 sed)的 shell 循环应该是这样的:

for file in *
do
    [ "$(sed -n '/^#include/p;q' "$file")" ] && printf '%s\n' "$file"
done
Run Code Online (Sandbox Code Playgroud)

如果密码中只有文件(不是目录)。

如果您需要打印文件的所有行,则类似于发布的第一个代码的解决方案将起作用(GNU 和 AT&T 版本):

sed -n '1{/^#include/!q};p'  file
Run Code Online (Sandbox Code Playgroud)

或者,(BSD 兼容 POSIXfied 版本):

sed -ne '1{/^#include/!q;}' -e p  file
Run Code Online (Sandbox Code Playgroud)

或者:

sed -n '1{
           /^#include/!q
         }
         p
       '  file
Run Code Online (Sandbox Code Playgroud)


Sté*_*las 6

for file in *; do
  [ -f "$file" ] || continue
  IFS= read -r line < "$file" || [ -n "$line" ] || continue
  case $line in
    ("#include"*) printf '%s\n' "$file"
  esac
done
Run Code Online (Sandbox Code Playgroud)

要打印文件的内容而不是其名称,请将printf命令替换为cat < "$file".

如果您awk支持nextfile扩展,并且您不关心打开非常规文件的潜在副作用:

awk '/^#include/{print substr(FILENAME, 3)}; {nextfile}' ./*
Run Code Online (Sandbox Code Playgroud)

上面,我们添加了一个./前缀,然后我们将其删除,FILENAME以避免包含=字符的文件名(或名为-)的文件名出现问题

有了zsh,您可以替换./*./*(-.)只普通文件传输(或符号链接像普通文件[ -f ... ]上面的方法)来awk

或者打印文件内容而不是名称:

awk 'FNR == 1 {found = /^#include/}; found' ./*
Run Code Online (Sandbox Code Playgroud)

(那个是便携式的)。