질문은여기패턴 일치 이전과 이후에 몇 줄을 요청합니다.
하지만 여기서 목표는 줄 번호를 가져와서 파일에서 그 앞과 뒤의 일부 줄을 가져오는 것입니다.
예:
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
소문과 다양한 벤치마크에 따르면 head + tail 조합이 다른 어떤 도구보다 훨씬 빠르다고 합니다.
$ 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개 요소 앞, 3줄 뒤를 중심으로 잘라내는 것입니다.\n
@F
perl -alF\\n -0777ne '$,=$\;print @F[6-4-1..6+3-1]' yourfile
결과
2
3
4
5
6
7
8
9