Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/455.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash 将grep管道传输到awk时修剪空白时出现问题_Bash_Awk_Sed_Grep - Fatal编程技术网

Bash 将grep管道传输到awk时修剪空白时出现问题

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编写一个简单的包装器,以便以更可读的格式输出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?
$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

只是完全误读了这个问题,并认为您误读了它。对不起!这个解决方案唯一的问题是原始的是给输出着色,而这不是。否则,这是一个很好的解决方案。我不确定是否a
grep--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。只是完全误读了这个问题,并认为你误读了。抱歉!这个解决方案唯一的问题是就是说原稿是着色输出的,而这不是。