我需要写一个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)
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)
(那个是便携式的)。