질문여기패턴 일치 전후에 몇 줄의 입력이 필요합니다.
하지만 여기서 목표는 줄 번호를 얻고 파일에서 줄 번호 앞과 뒤의 일부 줄을 가져오는 것입니다.
예를 들어:
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
.y
z
답변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