알 수 없는 행 수의 패턴 일치 또는 "...의 마지막 항목 바꾸기"와 같은 일부 문제의 경우 -z
GNU 옵션이 sed
정말 도움이 될 수 있습니다. 동일한 이식성을 어떻게 얻을 수 있습니까?
예: 파일이 있습니다.
yellow, green,
blue, black, purple,
orange,
white, red, brown
are some colours
파일의 마지막 쉼표를 로 바꾸고 싶습니다 and
. 쉼표가 어느 줄에 있는지, 줄의 어디에 있는지 알 수 없습니다. GNU로 sed
나는 할 수 있다
sed -z 's/\(.*\),/ \1 and/'
원하는 출력을 얻으십시오
yellow, green,
blue, black, purple,
orange,
white, red and brown
are some colours
POSIX에서 실행할 수 있는 이식 가능한 방식으로 이 작업을 어떻게 수행할 수 있습니까 sed
?
답변1
순수 POSIX에서는 sed
모든 줄을 직접 붙여넣어야 합니다. 일부 사람들은 N
루프 내에서 이 작업을 수행하지만 가장 쉬운 방법은 다음 패턴을 사용하여 예약된 공간에 추가하는 것입니다 H;1h;$!d;x
.
H
각 행을 예약된 공간에 추가합니다. 불행하게도 첫 번째 줄을 추가하면 버퍼 시작 부분에 개행 문자가 추가됩니다.1h
잘못된 개행을 방지하기 위해 첫 번째 줄의 예약된 공간을 덮어씁니다.$!d
마지막 행을 제외한 모든 행의 처리가 종료됩니다. 예약된 공간에 저장되므로 인쇄할 필요가 없습니다.x
마지막 라인 이후에만 실행되며(다른 모든 라인의 경우d
추가 명령 처리가 중지됨) 예약된 공간과 패턴 공간이 변경됩니다x
. 따라서 이 명령 이후에는 예약된 공간에 수집된 전체 파일이 패턴 공간에 있게 됩니다.-z
GNU를 선택합니다sed
. 물론g
대신 사용할 수도 있지만x
이렇게 하면 복사량이 많아지므로x
속도가 더 빨라집니다.
따라서 이 예제의 스크립트는 다음과 같습니다.
sed 'H;1h;$!d;x;s/\(.*\),/\1 and/'
참고하세요매우 큰 파일의 경우 RAM을 많이 사용하므로 이러한 파일을 처리하는 것은 좋지 않습니다.
답변2
sed는 단일 문자열에 대해 간단한 s/old/new 작업을 수행하는 데 사용됩니다. s, g, p(-n 포함) 이외의 구문을 사용하는 거의 모든 경우와 확실히 "공간 예약"에 대해 이야기하는 경우는 잘못된 도구를 사용하고 있는 것입니다. 이 작업과 같이 s/old/new보다 더 복잡한 작업의 경우 awk를 대신 사용해야 합니다. 다음은 UNIX 시스템의 모든 쉘에서 awk와 함께 작동하고 전체 파일을 메모리에 저장하지 않으며 텍스트로 다른 작업을 수행하려는 경우 조정하기 간단합니다.
$ cat tst.awk
/,/ { printf "%s", prev; prev="" }
{ prev = prev $0 ORS }
END {
if ( match(prev,/.*,/) ) {
prev = substr(prev,1,RLENGTH-1) " and" substr(prev,RLENGTH+1)
}
printf "%s", prev
}
$ awk -f tst.awk file
yellow, green,
blue, black, purple,
orange,
white, red and brown
are some colours
전체 파일을 메모리에 넣고 다음 신비한 룬을 작성하면 awk에서 더 간단하게 이 작업을 수행할 수 있습니다.
$ awk '{r=r$0 ORS} END{h=r;sub(/,[^,]+$/,"",h);sub(/.*,/,"",r);printf "%s and%s",h,r}' file
yellow, green,
blue, black, purple,
orange,
white, red and brown
are some colours
하지만 요점은 sed와 달리 그럴 필요가 없다는 것입니다.