用这个:

grep -A1 -B1 "test_pattern" file

将在文件中匹配的模式前后产生一行。是否有一种方法不显示行,而是显示指定数量的字符?

我的文件中的行相当大,所以我对打印整行不感兴趣,而只是在上下文中观察匹配。有什么建议吗?


当前回答

在gawk中,你可以使用match函数:

    x="hey there how are you"
    echo "$x" |awk --re-interval '{match($0,/(.{4})how(.{4})/,a);print a[1],a[2]}'
    ere   are

如果你可以使用perl,更灵活的解决方案:下面将在模式之前打印三个字符,然后是实际的模式,然后在模式之后打印5个字符。

echo hey there how are you |perl -lne 'print "$1$2$3" if /(.{3})(there)(.{5})/'
ey there how

这也可以应用于单词,而不仅仅是字符。下面将在实际匹配的字符串之前打印一个单词。

echo hey there how are you |perl -lne 'print $1 if /(\w+) there/'
hey

下面将在模式后面打印一个单词:

echo hey there how are you |perl -lne 'print $2 if /(\w+) there (\w+)/'
how

下面将在模式之前打印一个单词,然后是实际单词,然后是模式之后打印一个单词:

echo hey there how are you |perl -lne 'print "$1$2$3" if /(\w+)( there )(\w+)/'
hey there how

其他回答

在gawk中,你可以使用match函数:

    x="hey there how are you"
    echo "$x" |awk --re-interval '{match($0,/(.{4})how(.{4})/,a);print a[1],a[2]}'
    ere   are

如果你可以使用perl,更灵活的解决方案:下面将在模式之前打印三个字符,然后是实际的模式,然后在模式之后打印5个字符。

echo hey there how are you |perl -lne 'print "$1$2$3" if /(.{3})(there)(.{5})/'
ey there how

这也可以应用于单词,而不仅仅是字符。下面将在实际匹配的字符串之前打印一个单词。

echo hey there how are you |perl -lne 'print $1 if /(\w+) there/'
hey

下面将在模式后面打印一个单词:

echo hey there how are you |perl -lne 'print $2 if /(\w+) there (\w+)/'
how

下面将在模式之前打印一个单词,然后是实际单词,然后是模式之后打印一个单词:

echo hey there how are you |perl -lne 'print "$1$2$3" if /(\w+)( there )(\w+)/'
hey there how

如果使用ripgreg,你会这样做:

grep -E -o ".{0,5}test_pattern.{0,5}" test.txt 
grep -E -o ".{0,5}test_pattern.{0,5}" test.txt 

这将匹配最多5个字符前后你的模式。-o开关告诉grep只显示匹配项,-E则告诉grep使用扩展正则表达式。请确保在表达式周围加上引号,否则它可能会被shell解释。

你的意思是这样的:

grep -o '.\{0,20\}test_pattern.\{0,20\}' file

?

这将在test_pattern的两侧打印最多20个字符。\{0,20\}符号类似于*,但指定了0到20次重复,而不是0或更多。-o表示只显示匹配本身,而不是整行。

我永远不会轻易记住这些神秘的命令修饰符,所以我把上面的答案变成了~/中的一个函数。bashrc文件:(

cgrep() {
    # For files that are arrays 10's of thousands of characters print.
    # Use cpgrep to print 30 characters before and after search pattern.
    if [ $# -eq 2 ] ; then
        # Format was 'cgrep "search string" /path/to/filename'
        grep -o -P ".{0,30}$1.{0,30}" "$2"
    else
        # Format was 'cat /path/to/filename | cgrep "search string"
        grep -o -P ".{0,30}$1.{0,30}"
    fi
} # cgrep()

下面是它实际运行的样子:

$ ll /tmp/rick/scp.Mf7UdS/Mf7UdS.Source

-rw-r--r-- 1 rick rick 25780 Jul  3 19:05 /tmp/rick/scp.Mf7UdS/Mf7UdS.Source

$ cat /tmp/rick/scp.Mf7UdS/Mf7UdS.Source | cgrep "Link to iconic"

1:43:30.3540244000 /mnt/e/bin/Link to iconic S -rwxrwxrwx 777 rick 1000 ri

$ cgrep "Link to iconic" /tmp/rick/scp.Mf7UdS/Mf7UdS.Source

1:43:30.3540244000 /mnt/e/bin/Link to iconic S -rwxrwxrwx 777 rick 1000 ri

这个文件是一个连续的25K行,使用常规的grep是不可能找到你要找的东西的。

请注意调用与grep方法并行的cgrep的两种不同方式。

有一种“更好”的方法来创建函数,其中“$2”只在设置时传递,这将节省4行代码。不过我手边没有。比如${parm2} $parm2。如果我找到了,我会修改函数和这个答案。