인쇄 방법그리고 이전 줄뒤에 줄세 번째 행

인쇄 방법그리고 이전 줄뒤에 줄세 번째 행

질문여기패턴 일치 전후에 몇 줄의 입력이 필요합니다.

하지만 여기서 목표는 줄 번호를 얻고 파일에서 줄 번호 앞과 뒤의 일부 줄을 가져오는 것입니다.

예를 들어:

seq 10
1
2
3
4
5
6
7
8
9
10

줄 번호가 6인 경우 줄 앞에 4자리, 줄 뒤에 3자리를 입력해야 합니다. 그건

2
3
4
5
6
7
8
9

답변1

z=6   # focus line
x=4   # lines before
y=3   # lines after

start=$(( z - x ))
end=$(( z + y ))

사용 sed:

seq 10 | sed -n "$start,${end}p"
2
3
4
5
6
7
8
9

이는 명시적인 행 범위를 인쇄하기 위해 print( p) 명령을 사용합니다. sed다른 줄 무시를 사용하십시오 -n.

사용 awk:

seq 10 | awk -v start="$start" -v end="$end" 'NR >= start { print } NR >= end { exit }'
2
3
4
5
6
7
8
9

이는 Stéphane Chazelas의 답변과 유사하지만 awk;에서 구현된 스크립트는 start줄 수를 읽은 후 입력 줄 출력을 시작합니다. 줄 번호에서 end스크립트가 종료됩니다.

x두 가지 대안 모두 line 앞의 줄에서 시작하여 line 뒤의 줄에서 끝나는 입력 데이터의 일부를 표시합니다 z.yz

답변2

POSIX 쉘 사용:

$ before=4 after=3 line=6
$ seq 10 | sed "$((line-before)),\$!d; $((line+after))q"
2
3
4
5
6
7
8
9

다음과 같이 번역됨:

  • !( )를 제외하고 범위에서 모든 행을 제거합니다.알았어 - 전에마지막 항목부터 첫 번째 항목( $).
  • 적합줄 뒤 +세 번째

이렇게 하면 과거 내용을 굳이 읽지 않아도 됩니다.줄 뒤 +번째 줄.

그러나 이는 sed명령이 데이터 전송 직후에 계속해서 데이터를 전송하는 경우 SIGPIPE를 통해 명령이 중단되며 이는 원할 수도 있고 원치 않을 수도 있음을 의미합니다.

답변3

완전성을 위해 :

$ l=60;seq 100 |head -n$((l+3)) |tail -n+$((l-4))
56
57
58
59
60
61
62
63

소문과 다양한 벤치마크에 따르면 머리 + 꼬리 조합이 다른 도구보다 훨씬 빠릅니다.

$ a=1000000000
$ time seq $a |awk 'NR>=499998{print}NR >= 500004 { exit }' 
499998
499999
500000
500001
500002
500003

real    0m0.158s
user    0m0.152s
sys 0m0.004s

$ time seq $a |sed -n "499998,500003p"
499998
499999
500000
500001
500002
500003

real    1m30.249s
user    1m21.284s
sys 0m12.312s

$ time seq $a |sed "$((500000-2)),\$!d; $((500000+3))q"  #Stephan's Solution
499998
499999
500000
500001
500002
500003

real    0m0.052s
user    0m0.044s
sys 0m0.004s

$ time seq $a |head -n$((500000+3)) |tail -n+$((500000-2))
499998
499999
500000
500001
500002
500003

real    0m0.024s
user    0m0.024s
sys 0m0.004s

$ time seq $a |sed -n "499998,500003p;500004q"
499998
499999
500000
500001
500002
500003

real    0m0.056s
user    0m0.048s
sys 0m0.004s

답변4

# define line range constants
before=4
  line=6
 after=3

# setup the sed commands s.t. pattern space holds $before number
# of lines before we hit the line number $line and $after after
s='$!N'
p=`seq -s "$s"   "$before"`
a=`seq -s "$s" 0 "$after"`

N=${p//[0-9]/;}
n=${a//[0-9]/;}

# main...
seq 10 |
sed -e "
   1{ $N }
   \$d;N
   $line!D
   $n;q
"

또 다른 방법은 파일을 읽고 필드(현재 행)가 에 FS있도록 설정하는 것 입니다. 남은 것은 행 6과 앞과 뒤의 4개 요소를 잘라내는 것입니다.\n@F

perl -alF\\n -0777ne '$,=$\;print @F[6-4-1..6+3-1]' yourfile

결과

2
3
4
5
6
7
8
9

관련 정보