假设我位于一个包含很多文件的目录中。如何搜索目录中所有文件的内容并显示包含字符串“ER”但不包含“Cheese”的最长行?
到目前为止,据我所知,我正在尝试用一行命令来完成此操作。
我想我需要使用 grep -r 进行递归,以便搜索目录中的所有文件,但我的最终目标是只显示最长的行,所以我认为到目前为止它应该是这样的:
grep -r -e "ER"
当我出于小小的希望而附加-v“奶酪”时,它当然不起作用。
这不是用一行命令就可以实现的吗?如果是这样,我需要在多行中做什么?
答案1
这是一个 awk 解决方案:
awk '/ER/ && !/Cheese/ {if (length($0) > maxlen) { maxline=$0; maxlen=length($0);}} END {print maxlen, maxline;}' *
(它还打印最长行的长度,但如果您不想这样做,只需说... END {print maxline;}
.
相对于 Jeremy Dover 的 grep 解决方案的优点是它只传递一次输入。缺点是,如果有多行具有相同的最大长度,则仅打印第一行(如果使用 >= 比较长度,则仅打印最后一行); grep 解决方案打印所有这些。
答案2
这一行将满足您的要求(对于一个目录中的文件):
awk '{l=length($0)}/ER/&&!/Cheese/&&(length($0)>l){l=length($0);line=$0}END{print(line)}' *
如果有多行匹配,则仅打印第一的包含 ER(而不是 Cheese)且比之前选择的行更长的行。
此外,这将扫描 pwd (*) 中的文件。如果需要递归,则需要使用查找命令选择文件。
find . -type f -iname '*.sh' -exec sh -c 'awk '\''{l=length($0)}/ER/&&!/Cheese/&&(l>lm){lm=l;li=$0}END{print(li)}'\'' "$@"' awksh {} +
或者分几行(为了可读性):
find . -type f -iname '*.sh' -exec sh -c '\
awk '\''{l=length($0)}/ER/&&!/Cheese/&&(l>lm){lm=l;li=$0}END{print(li)}'\'\
' "$@"' awksh {} +
答案3
awk '/ER/ && !/Cheese/ && length > m {
m=length; d=$0; f=substr(FILENAME, 3); n=FNR
}
END { print m, f ":" n, d }' ./*
假设当前目录中只有常规文件,这将打印满足问题 ( m
) 中的条件的最长行的长度,以及找到该文件的文件名 ( f
)、行号 ( n
) 和行本身 ( d
)。
输出可能类似于
8 file:3 Hello ER
最长的一行有 8 个字符长,可以在名为 的文件的第 3 行找到file
。
答案4
在前面添加字符串的长度,按数字排序,然后打印第一个结果的第二个字段以获取原始字符串。
grep -h ER * | grep -v Cheese | awk '{ print length($0) " " $0}' | sort -nr| head -1| awk '{print $2}'
如果需要,此方法允许您执行比“MAX”或“MIN”更复杂的查询。注意AWK的使用。这正是它真正的好处。