이 문자열의 두 번째, 세 번째, 네 번째, 다섯 번째 점을 바꾸고 싶습니다.
2019-03-17T11:32:28.143343Z;1234.5678;901.234;567.89012;3456.78;192.168.0.1
쉼표를 사용하면 다음과 같은 결과를 얻을 수 있습니다.
2019-03-17T11:32:28.143343Z;1234,5678;901,234;567,89012;3456,78;192.168.0.1
첫 번째 쉼표와 여섯 번째 쉼표(및 그 이후의 모든 쉼표)는 변경되지 않은 상태로 유지되어야 합니다.
여러 번 실행할 수 있는 다음 명령을 찾았습니다(그러나 모범 사례는 아닐 수도 있음).
echo "$tmp" | sed 's/\./\,/2'
명령 하나로 이 작업을 어떻게 수행할 수 있나요?
답변1
데이터는 ;
6개의 구분된 필드로 구성되어 있으며 필드 2~5(1 또는 6 아님)의 점을 쉼표로 바꾸려고 합니다.
이것은 가장 간단한 방법입니다 awk
.
awk -F ';' 'BEGIN { OFS=FS } { for (i=2; i<=5; ++i) gsub("\\.", ",", $i); print }' file
주어진 예제 데이터를 기반으로 하면 다음과 같습니다.
2019-03-17T11:32:28.143343Z;1234,5678;901,234;567,89012;3456,78;192.168.0.1
코드는 단순히 ;
각 입력 줄의 -로 구분된 필드를 반복하고 루프가 반복하는 개별 필드에 대해 전역 검색 및 바꾸기를 호출합니다 ( 또는 에서 gsub()
수행하는 것처럼 ).s/\./,/g
y/./,/
sed
그런 다음 수정된 줄을 인쇄합니다.
이 -F
옵션은 입력 필드 구분 기호를 세미콜론으로 설정하고 해당 BEGIN
블록을 사용하여 출력 필드 구분 기호도 동일한 값으로 설정합니다(그렇지 않으면 공백으로 구분된 필드가 표시됩니다).
를 사용하면 sed
다음과 같은 작업을 수행할 수 있습니다.
sed 's/\./,/2; s/\./,/2; s/\./,/2; s/\./,/2' file
즉, 두 번째 점을 4번 교체합니다. 두 번째 점은 교체할 때마다 대체됩니다. 그러나 이는 각 필드 내의 값 개수가 고정되어 있다고 가정합니다.
이 문제를 해결하려면 필드에 점으로 구분된 내용이 두 개 이상 있는 경우 다음을 수행할 수 있습니다.
sed 'h; s/^[^;]*;//; s/;[^;]*$//; y/./,/; G;H;x; s/;[^\n]*\n/;/; s/\n.*;/;/' file
간단히 말해서, 이 명령이 수행하는 작업은 다음과 같습니다.
- 원래 행을 예약된 공간에 복사합니다.
- 패턴 공간에서 첫 번째 및 마지막 필드를 제거합니다.
- 패턴 공간의 모든 점을 쉼표로 변경합니다(명령어입니다
y
). 이제 쉼표로 변경했어야 할 점이 모두 변경되었습니다. 이제 패턴 공간의 중간 비트와 예비 공간의 원본 데이터에서 행을 재조립해야 합니다. G;H;x
패턴 공간에 다음을 포함하도록 (AND )- 원시 문자열 다음에 개행 문자가 옵니다.
- 수정된 중간 숫자 뒤에 개행 문자가 옵니다.
- 다시 원래 문자열입니다.
이제 패턴 공간에는 다음이 포함됩니다.세 줄. 첫 번째 줄의 첫 번째 필드와 개행 문자를 제외한 모든 항목을 제거하고 제거된 비트를
;
.마지막 줄과 비슷한 작업을 수행합니다. 즉, (현재 고유한) 개행 문자와 마지막 줄 앞의 모든 항목을 제거
;
하고 로 바꿉니다;
.완벽한.
아니면 그냥 awk
코드를 사용해도 됩니다.
답변2
;
다른 답변은 질문에 명시되지 않은 입력에 대해 가정을 하고 있기 때문에(예: 분리된 값 의 묶음이거나정확히6점), 나는 그 일을 수행하는 약간 서투른 답변을 제공하겠습니다.
sed 's/^\([^.]*\.[^.]*\)\.\([^.]*\)\.\([^.]*\)\.\([^.]*\)\./\1,\2,\3,\4,/'
이는 각 입력 행을 다음과 같이 분류합니다.
- 그룹 1 캡처: 줄의 처음부터 시작, 제외
.
, 그 다음에.
(줄의 첫 번째) 다음에 임의의 긴 문자 시퀀스가 옵니다. 단,.
, - ㅏ
.
(줄에서 두 번째), - 캡처 그룹 2: 제외
.
, - ㅏ
.
(행에서 세 번째), - 그룹 3 캡처: 제외
.
, - ㅏ
.
(행에서 네 번째), - 그룹 4 캡처: 제외
.
, - ㅏ
.
(행에서 다섯 번째), - 다음에 오는 내용(정규식과 일치하지 않지만 정규식이 로 끝나지 않기 때문에 행이 위보다 많을 수 있음
$
).
그리고 그것을로 교체
- 그룹 1 캡처: 두 번째까지 모든 것
.
이 줄(첫 번째 줄 포함)에서는 - ㅏ
,
(두 번째를 교체.
), - 그룹 2 캡처: 두 번째 그룹 사이의 모든 것
.
세 번째, - ㅏ
,
(세번째 교체.
), - 그룹 3 캡처: 세 번째 그룹 사이의 모든 것
.
네 번째, - ㅏ
,
(네 번째를 교체.
), - 그룹 4 캡처: 네 번째 그룹 사이의 모든 것
.
다섯 번째, - ㅏ
,
(다섯 번째 교체.
), - 5번째 이후 내용
.
.
따라서 두 번째, 세 번째, 네 번째 및 다섯 번째 점을 쉼표로 바꿉니다.
- 포인트가 5개 미만인 행은 변경되지 않습니다.
- 그러면 다섯 번째 포인트 이후의 포인트 수는 변경되지 않고 그대로 유지됩니다.
- 행에 점이 5개만 있어도(즉, 여섯 번째 점이 없음) 두 번째, 세 번째, 네 번째 및 다섯 번째 점이 대체됩니다.
GNU sed를 위한 또 다른 방법은 다음과 같습니다.
sed 's/\./\n/6g; s/\./,/2g; s/\n/./g'
s/\./\n/6g
여섯 번째 점부터 시작하는 모든 점을 개행 문자로 바꿉니다.s/\./,/2g
쉼표로 시작하는 모든 점을 두 번째 점으로 바꿉니다. 그러나 첫 번째 명령은 다섯 번째(있는 경우) 이후의 모든 포인트를 제거하기 때문에 실제로는 두 번째에서 다섯 번째까지만 해당됩니다.s/\n/./g
모든 줄 바꿈을 다시 점으로 변경합니다. 물론 줄에 있는 유일한 개행 문자는 원래 점이었던 문자이므로 원래의 점으로 다시 변경됩니다.
따라서 선에 점이 3개만 있으면 두 번째와 세 번째 점이 변경됩니다(네 번째와 다섯 번째 점이 존재하지 않더라도).
경고하다: 명령의 플래그로서 숫자와 a의 조합 의 동작은 다음 g
과 같습니다 .s
POSIX가 지정되지 않았습니다.
그리고 구현마다 다를 수 있습니다. 문서에 설명된 대로 GNU SED가 작동하는 방식입니다.GNU SED 매뉴얼.
답변3
루프가 있는 또 다른 sed:
sed ':A;s/\([^.]*\.[^.]*\)\.\(.*;[^;]*$\)/\1,\2/;tA' infile
답변4
sed
편집기를 사용하여 다음과 같이 이 문제를 해결할 수 있습니다.
$ sed -e '
y/./\n/
s/\n\(.*\)\n/.\1./
y/\n/,/
' input.txt
전제는 패턴 공간에 문자가 존재하지 않도록 먼저 모든 점을 개행 문자로 변환한다는 것입니다. 그런 다음 마지막과 첫 번째 개행 문자를 다시 점으로 변경합니다. 나머지 줄 바꿈은 모두 쉼표로 변환됩니다.
HTH.