명령의 범위 일치에서 N번째 줄을 "replaceString"으로 바꾸는 데 문제가 있습니다sed
. 즉, 범위 일치에서 N번째 줄을 상대적으로 바꿀 수 있습니까 ?
다음 입력 데이터를 고려하십시오.
1 a
start
3 h
4 7
end
6 iii
7 4
다음 명령을 사용하세요.
sed '/start/,/end/ { *s/.*/replaceString/ }'
위의 명령 대신 *
상대적으로 s/.*/replaceString/
일치하는 범위의 두 번째 줄에 명령을 실행하려면 어떻게 해야 합니까 ? 그래서 그것은 나에게 다음과 같은 예상 결과를 줄 것입니다.
1 a
start
replaceString
4 7
end
6 iii
7 4
이렇게 하면 두 번째 줄의 절대값이 전체 입력 파일로 변경되는데 이는 내가 원하는 것이 아닙니다.
$ sed '/start/,/end/{ 2s/.*/replaceString/}' infile
1 a
replaceString
3 h
4 7
end
6 iii
7 4
sed
특히 일치하는 범위의 줄 번호를 상대적으로 표현하는 방법을 이해하기 위해 이 작업을 수행하고 싶습니다 . 위치(줄 번호)start
그리고end
모드를 알 수 없습니다.
답변1
GNU를 사용하면 다음과 같이 주소 범위를 기계로 사용하여 내부 줄 수를 계산할 sed
수 있습니다 .addr1,+N
sed '/start/,/end/{/start/,+1{/start/,+0!s/.*/replaceString/}}'
# -------------------------------------^ This is Nth - 2
# --------------------------^ This is Nth - 1
# So for instance to replace the 4th line after "start"
# (the 5th including "start") you would do:
sed '/start/,/end/{/start/,+4{/start/,+3!s/.*/replaceString/}}'
따라서 기본적으로 경험 법칙은 *
"자리 표시자 주소"를 다음 표현식으로 바꾸는 것입니다.
/<first-pattern>/,+<N-1>{/<first-pattern>/,+<N-2>!
# of course ended by one right brace after the series of
# commands to execute for the Nth inner line
POSIXly 또 다른 접근 방식은 다음 스크립트와 같이 예약된 공간을 누산기로 사용하여 행 수를 기록하는 것입니다 sed
.
#!/usr/bin/sed -f
# In practice we add a '-' to hold-space for each inner line
# until we have added as many '-' as the number of the
# wanted Nth inner line.
# Here is an example to replace the 4th line after
# "start" (the 5th including "start")
/start/,/end/{
x;/^-\{0,4\}$/{ # here the numbers within braces must be 0,N-1
s/^/-/;/-\{5\}/{ # here the number within braces must be N
x;s/.*/replaceString/;bdone
}
}
x
:done
<here do text-manipulation common to all lines of start/end blocks>
b # _skip_ clearing the accumulator kept in hold-space
}
# clear the accumulator that we kept in hold-space
x;s/.*//;x
불편한 점은 카운트하는 동안 계속 공간을 차지한다는 것입니다. 그러나 최소한 버퍼링 없이 라인을 소비하므로 모든 크기의 파일에 대해 작동해야 합니다.
둘 다 단지 빠른 아이디어이므로 개선의 여지가 있을 수 있습니다.
답변2
어쩌면 다음과 같을 수도 있습니다:
sed '/start/{:a;N;/end/!ba;s/[^\n]*/replaceString/2}' file