我正在尝试为grep编写一个简单的包装器,以便以更易读的格式输出它的输出。这包括将匹配的字符串(在第二个冒号之后出现)放在新行上,并从匹配的字符串中修剪任何前导空格/制表符。
所以不要做以下事情:
$ grep -rnIH --color=always "grape" .
./apple.config:1: Did you know that grapes are tasty?
我希望能够得到这个:
$ grep -rnIH --color=always "grape" . | other-command
./apple.config:1:
Did you know that grapes are tasty?
我尝试过很多不同的方法来尝试这样做,包括使用sed,awk本身,替换,perl等。要记住的一件重要事情是我想要从3美元修剪前导空间,但3美元可能不会实际上包含整个匹配的字符串(例如,如果匹配的字符串包含带":"字符的URL)。
到目前为止,我已经达到了以下要点。
$ grep -rnIH --color=always "grape" . | \
awk -F ":" '{gsub(/^[ \t]+/, "", $3); out=""; for(i=4;i<=NF;i++){out=out$i}; print $1":"$2"\n"$3out}'
./apple.config:1:
Did you know that grapes are tasty?
gsub旨在从第二个冒号后发生的任何事件的开头修剪空白/制表符。然后for循环用于构建一个变量,该变量由匹配字符串中的任何其他内容组成,这些变量可能已被字段分隔符&#34;分开:&#34;。
我非常感谢能够正确修剪前导空白的任何帮助。
答案 0 :(得分:3)
对我来说,看起来你想匹配一条线,在这种情况下,显示它就像
file:line_number
line with the match
为此,您可以直接使用awk
:
awk -v OFS=":" '/pattern/ {print FILENAME, NR; print}' files*
FILENAME
代表您正在阅读的文件。NR
代表行号。OFS
代表输出字段分隔符,因此当您说print a, b
时,分隔符为:
。要删除前导或尾随空格,您可以使用gsub(/(^ *| *$)/,"")
,以便它们一起显示:
awk -v OFS=":" '/and/ {print FILENAME, NR; gsub(/(^ *| *$)/,""); print}' files*
查看示例:
$ tail a b
==> a <==
hello
this is some test
and i am done now
==> b <==
and here i am
done
现在让我们尝试匹配包含&#34;和&#34;:
的行$ awk -v OFS=":" '/and/ {print FILENAME, NR; gsub(/(^ *| *$)/,""); print}' a b
a:3
and i am done now
b:4
and here i am
答案 1 :(得分:1)
我最终使用grep,awk和sed的组合来解决我的问题并生成所需的输出格式。我想保留grep提供的彩色输出,当&#34; - color = always&#34;使用了选项,它最初引导我远离使用awk来执行文件内容匹配。
棘手的一点是,彩色的grep输出产生了意想不到的位置的颜色代码。因此,不可能从实际上以颜色代码开始的线修剪前导空白。第二个棘手的部分是我需要确保包含awk文件分隔符的匹配字符串(&#34;:&#34;在我的情况下)我们正确地再现。
我制作了以下bash包装函数 finds(),以便快速递归搜索目录中的文件内容。
#--------------------------------------------------------------#
# Search for files whose contents contain a given string. #
# #
# Param1: Substring to recursively search for in file contents.#
# Param2: Directory in which to search for files. [optional]. #
# Return: 0 on success, 1 on failure. #
#--------------------------------------------------------------#
finds() {
# Error if:
# - Zero or more than two arguments were provided.
# - The first argument contains an empty string.
if [[ ( $# -eq 0 ) || ( $# -gt 2 ) || ( -z "$1" ) ]]
then
echo "About: Search for files whose contents contain a given string."
echo "Usage: $FUNCNAME string [path-to-dir]"
echo "* string : string to recursively search for in file contents"
echo "* path-to-dir: directory in which to search files. [OPTIONAL]"
return 1 # Failure
fi
# (r)ecursively search, show line (n)umbers.
# (I)gnore binaries, s(H)ow filenames.
grep_flags="-rnIH"
if [ $# -eq 1 ]; then # No directory given; search from current directory.
rootdir="."
else # Search from specified directory.
rootdir="$2"
fi
# The default color code, with brackets
# escaped by backslashes.
def_color="\[m\[K"
grep $grep_flags --color=always "$1" $rootdir |
awk '
BEGIN {
FS = ":"
}
{
print $1":"$2
out = $3
for(i=4; i<=NF; i++) {
out=out":"$i
}
print out
}' |
sed -e "s/$def_color\s*/$def_color/"
return 0 # Success
}
我无法在上面的代码框中显示 def_color 的正确值(代码中显示的 \ [m <[K ]不正确)。要获得用于此变量的正确ANSI转义序列:
将grep --color = always的输出重定向到文本文件。
将以下突出显示的序列复制并粘贴为上面 finds()函数中 def_color 的值。
添加&#34; \&#34;每个括号前的转义字符。
将彩色grep输出写入文本文件的代码:
$ cd orange_test/
$ cat orange1.txt
I like to eat oranges.
$grep -r --color=always "orange" . > ./grep_out.txt
以下显示该函数产生的输出。请注意,您还可以在第二个参数中指定目录路径。
cheese_test/cheese1.txt
I like to eat cheese.
Do you all like cheese?
I like
when the cheese is
on my pizza.
you can find out more about
cheese at http://cheeseisgood.com
cheesestick