Shell 在AIX上,grep-B-A-m不起作用。使用sed或awk的任何解决方案

Shell 在AIX上,grep-B-A-m不起作用。使用sed或awk的任何解决方案,shell,Shell,我在AIX系统上。但是AIX上的grep不支持AIX系统上的-B、-A、-M。是否有其他类似于awk或sed的解决方案可以完成相同的工作 例如: str1 str2 str3 str4 str9 str8 str1 str3 str2 我尝试运行grepstr3-m1-b1-a1以获得: str2 str3 str4 但它在AIX上不起作用。对于sed或awk有什么解决方案吗?顺便说一句,祝贺您和+1提供示例输入和输出。你会惊讶于有多少问题缺少如此明显的规范 这可以通过ed(1)实现 so

我在AIX系统上。但是AIX上的
grep
不支持AIX系统上的
-B
-A
-M
。是否有其他类似于
awk
sed
的解决方案可以完成相同的工作

例如:

str1
str2
str3
str4
str9
str8
str1
str3
str2
我尝试运行
grepstr3-m1-b1-a1
以获得:

str2
str3
str4

但它在AIX上不起作用。对于
sed
awk
有什么解决方案吗?

顺便说一句,祝贺您和+1提供示例输入和输出。你会惊讶于有多少问题缺少如此明显的规范

这可以通过ed(1)实现

so ross$cat>>cg.ed
/str3/-1+2p
所以ross$ed-cg.txt
您可以使用此脚本生成一个脚本,该脚本将文件名和模式作为参数:

so ross$ cat > cg.sh
#!/bin/sh
ed - $1 << eof
/$2/-1;.+2p
eof
so ross$ sh cg.sh cg.txt str3
str2
str3
str4
so ross$ 
so ross$cat>cg.sh
#!/垃圾箱/垃圾箱

ed-$1我有一个78行的shell脚本来完成这项工作。后来我用一个114行的Perl脚本替换了它,但通常将GNU
grep
移植到我需要的地方。shell脚本如下-它对选项使用了不同的命名法(AFAIK,它早于GNU grep上的选项;它当然是独立于GNU grep中的选项开发的)


您可以使用一个循环缓冲区,在找到匹配项时打印该缓冲区,然后是匹配行,然后是附加行

#!/usr/bin/awk -f
BEGIN {
    B = 4              # set these values like you would use for grep -B, -A, -m
    A = 2
    m = 3

    patt = "999"       # set this to your regex

    i = 0
    B++                # the buffer will hold B lines plus one for the match
}

{
    a[i] = $0          # accumulate B (+1) lines in a circular buffer
    i = (i + 1) % B
}

$0 ~ patt {            # if the pattern is found print the contents of the buffer
    for (j=1; j<=B; j++) {
        print a[i]
        i = (i + 1) % B
    }
    split("", a)
    for (i=1; i<=A; i++) {    # print the next A lines
        getline
        print
    }
    if (--m == 0) exit        # output m matches then quit
    print "---"
}
#/usr/bin/awk-f
开始{
B=4#设置这些值,就像您将用于grep-B、-A、-m一样
A=2
m=3
patt=“999”#将其设置为您的正则表达式
i=0
B++#缓冲区将保存B行加上一行用于匹配
}
{
a[i]=$0#在循环缓冲区中累积B(+1)行
i=(i+1)%B
}
$0~patt{#如果找到模式,则打印缓冲区的内容

对于(j=1;j,这个小编码将突出显示regexp,其工作原理类似于grep-A-B-m 希望这有帮助

克努尔

#!/bin/bash
[ $# -lt 2 ] && printf "usage: %s <regex> <file> [[[back]forward]occurrence] \n" "$0" && exit 0
REGEX=$1
FILE=$2
BACK=${3:-1}
FORWARD=${4:-1}
STOP=${5:-1000000000}
awk -v bold=$'\e[1m' -v norm=$'\e[0m' -v back=$BACK -v forward=$FORWARD -v stop=$STOP 'BEGIN {cnt=0} { array[i++]=$0 }
     END {
       maxI=++i
       for (j=0;j<maxI; j++) {
         if (array[j] ~ /'"${REGEX}"'/) {
           for (z=back;z>0; z--) {
             print array[j-z]
           }
           printf bold > "/dev/stderr"
           printf("%s\n", array[j])
           printf norm > "/dev/stderr"
           for (x=1;x<=forward; x++) {
             print array[j+x]
           }
           cnt++
           if (cnt == stop) {
             break
           }
         }
       }
     }
   ' "$FILE"
!/bin/bash
[$#-lt 2]&&printf“用法:%s[[[back]forward]出现]\n“$0”&退出0
正则表达式=$1
文件=$2
后退=${3:-1}
正向=${4:-1}
停止=${5:-100000000}
awk-v bold=$'\e[1m'-v norm=$'\e[0m'-v back=$back-v forward=$forward-v stop=$stop'BEGIN{cnt=0}{array[i++]=$0}
结束{
maxI=++i
对于(j=0;j0;z--){
打印阵列[j-z]
}
printf bold>“/dev/stderr”
printf(“%s\n”,数组[j])
printf norm>“/dev/stderr”
对于(x=1;x稍微简化的,额外打印所有匹配行,而不仅仅是第一行匹配
str3
模式:

echo ',g/str3/-1;+2p' | ed - myFile.txt 
在哪里

如果只想打印第一次出现的内容,则命令更简单:

echo '/str3/-1;+2p' | ed - myFile.txt
在哪里


如果你在str9之后需要3行,这里有一个简单的

输入文件

$cat <<'EOF' > strfile.txt
str1
str2
str3
str4
str9
str8
str1
str3
str2
EOF

谢谢你的回复。我以前从未使用过ed命令。我会尝试一下。awk或sed如何?thx!请你稍微解释一下该命令。在grep中匹配的like-B之前为行号设置了哪个参数。在grepuse c中匹配的like-a之后为行号设置了哪个参数。(你可以用任何数字表示c)。行前用
p
表示。但是,对于这一点,我只给出了与
-a1
等价的答案。如果你想指定数字,就必须用另一种方法。对于-a1(在找到的一行之后打印该行),你对其他要求还有什么想法吗?(-m 1=仅查找第一个引用,-B 1=打印引用之前的行)?
echo ',g/str3/-1;+2p' | ed - myFile.txt 
,                 # read all lines (from first to the very last)
 g/str3/          # search for `str3` string
        -1        # take 1 line BEFORE the matching one
          ;+2     # and also next 2 lines (so 3 lines in total)
             p    # and print them
echo '/str3/-1;+2p' | ed - myFile.txt
/str3/          # find line matching the `str3` string
      -1        # take 1 line BEFORE the matching one
        ;+2     # and also next 2 lines (so 3 lines in total)
           p    # and print them
$cat <<'EOF' > strfile.txt
str1
str2
str3
str4
str9
str8
str1
str3
str2
EOF
$awk '/str9/{print FILENAME;n=NR+3} n>=NR' strfile.txt

strfile.txt
str9
str8
str1
str3