sed로 4번 교체

sed로 4번 교체

이 문자열의 두 번째, 세 번째, 네 번째, 다섯 번째 점을 바꾸고 싶습니다.

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/\./,/gy/./,/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

간단히 말해서, 이 명령이 수행하는 작업은 다음과 같습니다.

  1. 원래 행을 예약된 공간에 복사합니다.
  2. 패턴 공간에서 첫 번째 및 마지막 필드를 제거합니다.
  3. 패턴 공간의 모든 점을 쉼표로 변경합니다(명령어입니다 y). 이제 쉼표로 변경했어야 할 점이 모두 변경되었습니다. 이제 패턴 공간의 중간 비트와 예비 공간의 원본 데이터에서 행을 재조립해야 합니다.
  4. G;H;x패턴 공간에 다음을 포함하도록 (AND )

    1. 원시 문자열 다음에 개행 문자가 옵니다.
    2. 수정된 중간 숫자 뒤에 개행 문자가 옵니다.
    3. 다시 원래 문자열입니다.
  5. 이제 패턴 공간에는 다음이 포함됩니다.세 줄. 첫 번째 줄의 첫 번째 필드와 개행 문자를 제외한 모든 항목을 제거하고 제거된 비트를 ;.

  6. 마지막 줄과 비슷한 작업을 수행합니다. 즉, (현재 고유한) 개행 문자와 마지막 줄 앞의 모든 항목을 제거 ;하고 로 바꿉니다 ;.

  7. 완벽한.

아니면 그냥 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 과 같습니다 .sPOSIX가 지정되지 않았습니다. 그리고 구현마다 다를 수 있습니다. 문서에 설명된 대로 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.

관련 정보