Bash 将grep管道传输到awk时修剪空白时出现问题
我正在尝试为grep编写一个简单的包装器,以便以更可读的格式输出grep。这包括将匹配的字符串(出现在第二个冒号之后)放在新行上,并从匹配的字符串中删除任何前导空格/制表符 因此,不要执行以下操作:Bash 将grep管道传输到awk时修剪空白时出现问题,bash,awk,sed,grep,Bash,Awk,Sed,Grep,我正在尝试为grep编写一个简单的包装器,以便以更可读的格式输出grep。这包括将匹配的字符串(出现在第二个冒号之后)放在新行上,并从匹配的字符串中删除任何前导空格/制表符 因此,不要执行以下操作: $ grep -rnIH --color=always "grape" . ./apple.config:1: Did you know that grapes are tasty? 我希望能够获得以下信息: $ grep -rnIH --color=always "grape" . | o
$ 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?
$grep-rnIH--color=总是“葡萄色”\
awk-F:“{gsub(/^[\t]+/,”,$3);out=“”;for(i=4;i对我来说,它看起来像是要匹配一行,在这种情况下,显示为
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
对我来说,它看起来像你想要匹配一条线,在这种情况下,显示它像
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
我最终使用了grep、awk和sed的组合来解决问题并生成所需的输出格式。我希望保留grep在使用“-color=always”选项时提供的彩色输出,该选项最初引导我避免使用awk来执行文件内容匹配
棘手的一点是,彩色grep输出在意外的位置生成了颜色代码。因此,不可能从实际上以颜色代码开头的行中删除前导空格。第二个棘手的部分是,我需要确保匹配的字符串包含awk文件分隔符(“:”)我们复制得很好
为了快速递归地搜索目录中的文件内容,我创建了以下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
}
使用函数
下面显示了该函数生成的输出。请注意,您还可以在第二个参数中指定目录路径
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
我最终使用了grep、awk和sed的组合来解决问题并生成所需的输出格式。我希望保留grep在使用“-color=always”选项时提供的彩色输出,该选项最初引导我远离使用awk来执行文件内容匹配
棘手的一点是,彩色grep输出在意外的位置生成了颜色代码。因此,不可能从实际上以颜色代码开头的行中删除前导空格。第二个棘手的部分是,我需要确保匹配的字符串包含awk文件分隔符(“:”)我们复制得很好
为了快速递归地搜索目录中的文件内容,我创建了以下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
}
使用函数
下面显示了该函数生成的输出。请注意,您还可以在第二个参数中指定目录路径
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
只是完全误读了这个问题,并认为您误读了它。对不起!这个解决方案唯一的问题是原始的是给输出着色,而这不是。否则,这是一个很好的解决方案。我不确定是否agrep--color=always-B1 grape
(或者在答案中搜索任何单词-'and')作为一个后处理器,可以适当地解决问题。可能不是;grep
倾向于在文本块之间放置分隔符。(例如,printf“%s\n”a b c b d b”| grep-B1--color=always b
输出只包含--
的行(两个破折号)。我想一个后置处理器:grep-v'^--$'
可以处理这个问题,但它有点讨厌。)@JonathanLeffler对于这种情况,有一个神奇的--无组分隔符
选项可以防止那些--
在匹配之间。所以,是的,你的建议很好!我的解决方案| grep--无组分隔符--color=always-B1葡萄
应该可以。我更喜欢你的答案如何处理前导空格b在添加颜色转义序列之前(如果按照@JonathanLeffler的建议将管道连接到grep)。如果我像下面所做的那样将其封装在bash函数中,您会建议如何防止awk处理子目录时将其视为文件?我只能通过将find管道化到awk中来指定文件,但这会创建您指出的在我的解决方案中并不理想的双重管道。良好的学习体验,谢谢。@user1764386这是一个v这是一个很好的问题,我现在还没有解决方案。你可以说awk'.'*
,而awk在匹配目录时会显示一些错误,所以你可以用awk'.'.'*2>/dev/null
将它们重定向到stderr。只是完全误读了这个问题,并认为你误读了。抱歉!这个解决方案唯一的问题是就是说原稿是着色输出的,而这不是。