让我们假设我在一个包含很多文件的目录中。您将如何搜索目录中所有文件的内容并显示包含字符串“ER”但不包含“Cheese”的最长行?
到目前为止,据我所知,我正在尝试在一行命令中执行此操作。
我想我需要使用 grep -r 进行递归,以便搜索目录中的所有文件,但我的最终目标是只显示最长的行,所以我认为到目前为止它应该是这样的:
grep -r -e "ER"
Run Code Online (Sandbox Code Playgroud)
当我出于小小的希望将 -v "Cheese" 附加到它时,它当然不起作用。
这不能用一行命令吗?如果是这样,我需要在多行中做什么?
Nic*_*ckD 13
这是一个 awk 解决方案:
awk '/ER/ && !/Cheese/ {if (length($0) > maxlen) { maxline=$0; maxlen=length($0);}} END {print maxlen, maxline;}' *
Run Code Online (Sandbox Code Playgroud)
(它还打印最长行的长度,但如果您不想要那样,只需说... END {print maxline;}
.
Jeremy Dover 的 grep 解决方案的优势在于它对输入进行一次传递。缺点是如果有多条最大长度相同的行,它只打印第一行(如果使用 >= 比较长度,则打印最后一行);grep 解决方案打印所有这些。
这一行将执行您的要求(对于一个目录中的文件):
awk '{l=length($0)}/ER/&&!/Cheese/&&(length($0)>l){l=length($0);line=$0}END{print(line)}' *
Run Code Online (Sandbox Code Playgroud)
如果有几行匹配,这将只打印包含 ER的第一行,而不是 Cheese 并且比以前选择的行长。
此外,这将扫描密码 (*) 中的文件。如果需要递归,则需要使用 find 命令选择文件。
find . -type f -iname '*.sh' -exec sh -c 'awk '\''{l=length($0)}/ER/&&!/Cheese/&&(l>lm){lm=l;li=$0}END{print(li)}'\'' "$@"' awksh {} +
Run Code Online (Sandbox Code Playgroud)
或者在几行中(为了可读性):
find . -type f -iname '*.sh' -exec sh -c '\
awk '\''{l=length($0)}/ER/&&!/Cheese/&&(l>lm){lm=l;li=$0}END{print(li)}'\'\
' "$@"' awksh {} +
Run Code Online (Sandbox Code Playgroud)
awk '/ER/ && !/Cheese/ && length > m {
m=length; d=$0; f=substr(FILENAME, 3); n=FNR
}
END { print m, f ":" n, d }' ./*
Run Code Online (Sandbox Code Playgroud)
假设当前目录中只有常规文件,这将打印满足问题中条件的最长行的长度 ( m
),以及找到它的文件名 ( f
)、行号 ( n
) 和行本身 ( d
)。
输出可能看起来像
8 file:3 Hello ER
Run Code Online (Sandbox Code Playgroud)
最长的一行有 8 个字符,位于名为file
.