将grep传递给awk

时间:2015-11-27 19:05:11

标签: bash awk sed grep

我正在尝试为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;。

我非常感谢能够正确修剪前导空白的任何帮助。

2 个答案:

答案 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
}
  1. grep 用于递归查找指定目录中包含的文件内容中的匹配字符串。
  2. awk 用于打印&#34; filename:linenumber&#34;,然后构建一个包含其余参数的变量,由字段分隔符&#34;分隔:&# 34 ;.这允许我们重新组合匹配字符串的其余部分,以防它被初始分割(例如,包含&#34; http://&#34;的URL)。
  3. sed 用于修剪输出行中的任何前导空格/制表符。这里它匹配默认颜色代码(后跟可变数量的空间)并将其替换为自身(没有尾随空格)。
  4. 设置def_color的正确值

    我无法在上面的代码框中显示 def_color 的正确值(代码中显示的 \ [m <[K ]不正确)。要获得用于此变量的正确ANSI转义序列:

    1. 将grep --color = always的输出重定向到文本文件。

    2. 将以下突出显示的序列复制并粘贴为上面 finds()函数中 def_color 的值。

    3. 添加&#34; \&#34;每个括号前的转义字符。

    4. 将彩色grep输出写入文本文件的代码:

      $ cd orange_test/
      $ cat orange1.txt
      I like to eat oranges.
      $grep -r --color=always "orange" . > ./grep_out.txt
      

      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
      

      grep_out2