확장 정규식을 사용하여 sed 스크립트를 만드는 방법

확장 정규식을 사용하여 sed 스크립트를 만드는 방법

csv 파일의 명령줄에서 개별적으로 실행할 때 완벽하게 작동하는 두 개의 sed 명령이 있습니다. 둘 다 csv 파일 열 중 하나의 소수점 형식을 수정하고 소수점 이하 자릿수를 두 자리로 반올림하도록 설계되었습니다.

- 소수점 이하 자릿수가 하나만 있는 숫자에 0을 추가합니다.

sed -r -e  's/[0-9]\;[0-9]+\.[0-9]/&0/'

- 소수점 이하 두 자리 이상의 반올림 숫자:

sed -re 's/([0-9]+\.[0-9]{2})[0-9]+/\1/' 

이제 동시에 적용할 수 있도록 sed 스크립트에 넣고 싶습니다. 저는fixed_floats.sed라는 스크립트를 만들었습니다.

    #!/bin/sed

s/[0-9]\;[0-9]+\.[0-9]/&0/
s/(\[0-9]+\.[0-9]{2}\)[0-9]+/\1/

다음 명령을 사용하여 실행하려고 하면:

sed -f fix_floats.sed titanic-passengers.csv

출력에서 아무 것도 변경되지 않는 것 같습니다. (sed 명령의 정규식이 확장되어 있으므로 작동하지 않는 이유는 스크립트를 실행할 때 지정하지 않았기 때문인 것 같습니다.)

다음 명령을 사용하여 실행하려고 하면:

sed -E -f fix_floats.sed titanic-passengers.csv

다음 오류가 발생합니다.

sed: file fix_floats.sed line 5: invalid reference \1 on `s' command's RHS

csv에 효율적으로 적용할 수 있도록 확장 정규식을 사용하여 sed 스크립트를 만드는 방법에 대한 제안 사항이 있습니까?

원시 출력: (관심 있는 열은 행 끝에서 세 번째 열입니다.)

356;No;3;Vanden Steen, Mr. Leo Peter;male;28.0;0;0;345783;9.5;;S
546;No;1;Nicholson, Mr. Arthur Ernest;male;64.0;0;0;693;26.0;;S

원하는 출력:

356;No;3;Vanden Steen, Mr. Leo Peter;male;28.0;0;0;345783;9.50;;S
546;No;1;Nicholson,Mr.Arthur Ernest;male;64.0;0;0;693;26.00;;S

답변1

스크립트의 마지막 줄은 명령줄에서 실행되는 스크립트와 다릅니다. 두 개의 백슬래시를 추가할 이유가 없습니다.

s/(\[0-9]+\.[0-9]{2}\)[0-9]+/\1/

~해야 한다

s/([0-9]+\.[0-9]{2})[0-9]+/\1/

(또한 첫 번째 명령에서 세미콜론을 이스케이프할 필요는 없지만 s///그냥 무시되기 때문에 문제가 되지 않습니다.)

답변2

다음과 같이 부동 소수점 숫자의 형식을 지정할 수 있는 언어를 사용하는 것이 더 쉽습니다.

$ awk -F ';' 'BEGIN { OFS=FS } { $(NF-2) = sprintf("%.2f", $(NF-2)) }; 1' file
356;No;3;Vanden Steen, Mr. Leo Peter;male;28.0;0;0;345783;9.50;;S
546;No;1;Nicholson, Mr. Arthur Ernest;male;64.0;0;0;693;26.00;;S

프로그램 은 끝에서부터 시작하여 awk세 번째 구분 필드를 소수점 이하 두 자리의 부동 소수점 숫자로 다시 작성합니다 . ;이것은 반올림을 수행하므로 0.009가 됩니다 0.01. 잘라 내기 호출 대신에 사용합니다 int($(NF-2)*100)/100).$(NF-2)sprintf()


표현 sed에 백슬래시가 너무 많습니다. 특히 캡처링 그룹을 종료해야 하는 확장 정규식에서 which를 사용했고 \)중요한 대괄호 표현식을 비활성화하기 위해 which를 사용했으며 대신 불필요한 부분을 사용했습니다.)\[[\;;

표준 sed용어로 표현하면 다음과 같습니다.

s/\(\.[0-9]\)\(\(;[^;]*\)\{2\}\)$/\10\2/
s/\(\.[0-9][0-9]\)[0-9]\{1,\}\(\(;[^;]*\)\{2\}\)$/\1\2/

확장 정규식과 동일합니다(현재는 다음과 함께 사용하기 위한 비표준입니다 sed -E.

s/(\.[0-9])((;[^;]*){2})$/\10\2/
s/(\.[0-9][0-9])[0-9]+((;[^;]*){2})$/\1\2/

이는 수정한 필드 뒤의 마지막 두 필드와 명시적으로 일치하므로 표현식보다 안전합니다. 따라서 실수로 임의의 부동 소수점 값을 수정할 위험이 적습니다.

관련 정보