首页 > 学技术 > 技术网文 > Linux Shell > 正文

[保留] awk打印指定行的前m后n行。


来源 chinaunix.net 酷勤网整理

1。
awk 'BEGIN{m=2;n=3;i=1;nr_up=0;nr_down=0;}

        {
         for(i=1;i<=m;i++)
        {
                up=up[i+1];
        }
        up[m+1]=$0;
        }
        /^4$/{
                for(j=1;j<=m;j++)
                {
                        if(up[j])
                                print up[j];
                        else
                                continue;
                }
                print $0;
                flag=n;
                next;
            }
        {if(flag>0)
        {
                print $0;
                flag --;
        }
}' 



2。

awk 'BEGIN{m=2;n=3;i=1;nr_up=0;nr_down=0;num=0}
        NR<=m{
         str=str"\n"$0;
        }
        NR>=m{
                        str=substr(str,index(str,"\n")+1)"\n"$0;
        }

        /^4$/{
                print str;
                flag=n;
                next;
            }
        {if(flag>0)
        {
                print $0;
                flag --;
        }
}' 



3。

awk 'BEGIN{m=2;n=3;i=1;nr_up=0;nr_down=0;}
        {
         for(i=1;i<=m;i++)
        {
                up=up[i+1];
        }
        up[m+1]=$0;
        }
        /^4$/{
                if(nf_up=0)
                        nr_up=NR;
                else
                {
                        if(nr_down!=0)
                                nr_up=nr_down;
                        nr_down=NR;
                }
                if(nr_down!=0 && nr_up!=0 && nr_down-nr_up<=m+n)
                {
                        for(i=1;i<=m+n-(nr_down-nr_up-1);i++)
                        {
                                delete up;
                        }
                }
                for(j=1;j<=m;j++)
                {
                        if(up[j])
                                print up[j];
                        else
                                continue;
                }
                print $0;
                flag=n;
                next;
            }
        {if(flag>0)
        {
                print $0;
                flag --;
        }
}'


4。

awk 'BEGIN{m=2;n=3;i=1;nr_up=0;nr_down=0;num=0}
        NR<=m{
         str=str"\n"$0;
        }
        NR>=m{
                if(num>0)
                {
                        str=str"\n"$0;
                        num--;
                }
                else
                {
                        str=substr(str,index(str,"\n")+1)"\n"$0;
                }
        }

        /^4$/{
                if(nf_up=0)
                        nr_up=NR;
                else
                {
                        if(nr_down!=0)
                                nr_up=nr_down;
                        nr_down=NR;
                }
                if(nr_down!=0 && nr_up!=0 && nr_down-nr_up<=m+n)
                {
                        for(i=1;i<=m+n-(nr_down-nr_up-1);i++)
                        {
                                str=substr(str,index(str,"\n")+1);
                                ++num;
                                if(num>m)
                                {
                                        num--;
                                        break;
                                }
                        }
                }
                print str;
                flag=n;
                next;
            }
        {if(flag>0)
        {
                print $0;
                flag --;
        }
}' 



1,2只是简单的实现。
3,4考虑了一些特殊情况(可能会有没有考虑到的情况)。

基本算法:把当前行的前m行保存起来,如果当前行是满足条件的记录,则打印前m行,然后把flag=n,继续打印以后的n行记录。



 wingger 回复于:2005-10-09 21:40:30

:roll: 用grep 的-A1 -B1也行吧


 wmjie 回复于:2005-10-09 23:13:14

刚刚学awk。
嘿嘿。


 寂寞烈火 回复于:2005-10-10 02:15:20

引用:原帖由 "wmjie" 发表:

1,2只是简单的实现。
3,4考虑了一些特殊情况(可能会有没有考虑到的情况)。

基本算法:把当前行的前m行保存起来,如果当前行是满足条件的记录,则打印前m行,然后把flag=n,继续打印以后的n行记录。


写的漂亮!!! 不过,似乎没那么复杂吧  :mrgreen:


 莫凭栏 回复于:2005-10-10 04:18:44

引用:原帖由 "寂寞烈火" 发表:

写的漂亮!!! 不过,似乎没那么复杂吧  :mrgreen:


对哟,人家可是“聪明的傻瓜 ” :em06:


 styr 回复于:2005-10-10 15:01:27

NB,先CV下来,慢慢看,支持..............


 wmjie 回复于:2005-10-10 20:25:20

引用:原帖由 "莫凭栏" 发表:

对哟,人家可是“聪明的傻瓜 ” :em06:



虽然我是傻瓜,但是我很聪明哦~~ :mrgreen:  :mrgreen: 

一直以为awk跟c语言差不多,虽然两者有些差别,但是还是很方便的说。


 寂寞烈火 回复于:2005-10-11 03:01:13

引用:原帖由 "wmjie" 发表:


虽然我是傻瓜,但是我很聪明哦~~ :mrgreen:  :mrgreen: 

一直以为awk跟c语言差不多,虽然两者有些差别,但是还是很方便的说。


兄台能写出这样的script,足以见证兄台的功底!!!  :em06:


 lych 回复于:2005-10-11 08:39:46

前m行!既然知道了行数,好像就不要这么复杂的吧


 wmjie 回复于:2005-10-12 00:19:24

如何才能知道 /^4$/ 的行数?
只有到底这条记录的时候才能知道他的行数吧?


 lych 回复于:2005-10-12 11:24:43

如打印file的前m行
sed -n '1,mp' file


 sqp1982 回复于:2005-10-12 12:13:59

cat test
1
2
3
4
5
6
7
8
9
0
打印前3行和后3行
awk 'NR<4 || NR> 7 {print $1}' test 
1
2
3
8
9
0


 wmjie 回复于:2005-10-12 21:49:35

打印4的前三行,后三行如何打印?


 sqp1982 回复于:2005-10-13 09:52:50

awk 'NR<5 || NR> 7 {print $1}' test


 wmjie 回复于:2005-10-13 22:48:18


1
2
3
4
5
6
7
8
9
80
4
81
82
4
83
84
85
86
87
88
89
90
91
92
93
4
94
95
96
97
98
99
100

查找 /^4$/ 的前2,后3行



2
3
4
5
6
7
9
80
4
81
82
4
83
84
85
92
93
4
94
95
96



 hygs 回复于:2005-11-12 22:31:48

引用:查找 /^4$/ 的前2,后3行


 





[font=黑体][color=Blue][size=2]关注![/size][/color][/font]!!


 ivhb 回复于:2005-11-13 14:34:41


#!/usr/bin/ksh

#
#
# rgrep               当指定一个搜索模式 pattern 时候, 可以用 
# -p num              搜索模式匹配行以及之前 num 行一并显示
# -n num              搜索模式匹配行以及之后 num 行一并显示
# -r num              搜索模式匹配行以及前/后 num 行一并显示
# -s pattern          指定搜索模式
#
# file1 [ file2 ... ] 为搜索文件范围,
#
# 1. 如果没有指定p, n, r, 则显示匹配行
#
# 2. 如果模式为空字串"", 如 ls | rgrep -s "" , 而不能写成 ls | rgrep -s""
# 该语句得到的结果为所有的行
#
# 3. 运行环境必须是 ksh
#

usage()
{
  printf "usage : ${0##*/} [ [ -r num ] [ [ -p num ] [ -n num ] ] ] -s pattern [ file1 [ file2 file3 ... ] ]n"
}

plines=0
nlines=0

while getopts r:p:n:s: name; do
  case $name in 
  r)
    rflg=1
    plines="$OPTARG"
    nlines="$OPTARG"
    ;;
  p)
    pflg=1
    plines="$OPTARG"
    ;;
  n)
    nflg=1
    nlines="$OPTARG"
    ;;
  s)
    sflg=1
    ptn="$OPTARG"
    ;;
  esac
done

shift $((OPTIND - 1))

#
# 必须指定搜索模式
#
if [ X$sflg = X ]; then
  usage; exit 1
fi

#如果没有指定filelist
#if [ $# -lt 1 ]; then
#  usage; exit 1
#fi

filelist="$*"

awk -vpre_lines=$plines -vnext_lines=$nlines -vpattern="$ptn" '
BEGIN {
  pre_lines = pre_lines + 0; next_lines = next_lines + 0
  total = pre_lines + next_lines + 1
}
{
  save_line[NR % total] = $0
  if (NR - next_lines > 0 
    && match(save_line[(NR - next_lines) % total], pattern)) {
    i = NR - total + 1 > 0 ? NR - total + 1 : 1
    for (; i < NR + 1; i ++)
      print save_line[i % total]
    sav_match_line = NR
  }
}
END {
  if (sav_match_line != NR && next_lines > 0) {
    i = NR - total + 1 > 0 ? NR - total + 1 : 1
    for (; i < NR + 1; i ++)
      if (match(save_line[i % total], pattern)) {
        for (j = i - pre_lines > 0 ? i - pre_lines : 1; j < NR + 1; j ++)
          print save_line[j % total]
      }
  }
}' $filelist





 寂寞烈火 回复于:2005-11-14 03:12:43

引用:原帖由 wmjie 于 2005-10-12 21:49 发表
打印4的前三行,后三行如何打印? 


变态的 :mrgreen: 
引用:
/home/lee#seq 20>a
/home/lee#cat a
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

grep:

/home/lee#grep -A3 -B2 '^4' a
2
3
4
5
6
7
变态的

/home/lee#
> sed -n "$(($(sed -n "/^4/=" a)-2)),$(($(sed -n "/^4/=" a)+3))p" a
2
3
4
5
6
7



 zhhui2000 回复于:2005-11-16 11:49:21

引用:原帖由 hygs 于 2005-11-12 22:31 发表




[font=黑体][color=Blue][size=2]关注![/size][/color][/font]!! 



搞了个SED版,不严格。前三后二。
#!/usr/bin/sed -nf
1h;
1!H;
/^4$/{
        g;
        N;N;
        p;
        h;
}
1,3!{
g;
s/\(.*\)\n\(.*\)/2/;
h;
}


 ronwa 回复于:2006-05-16 16:52:04

awk '(NR<4 && NR>0) || (NR>4 && NR<8) {print}' num.txt




原文链接:http://bbs.chinaunix.net/viewthread.php?tid=624057
转载请注明作者名及原文出处



收藏本页到: