`sed expr1 | sed expr2`가 `sed -e expr1 -e expr2`와 다른 이유

`sed expr1 | sed expr2`가 `sed -e expr1 -e expr2`와 다른 이유

id사용자가 속한 그룹의 더 읽기 쉬운 목록을 한 줄씩 제공하기 위해 출력을 분리했습니다 .

id roaima | sed 's/,/\n\t/g'
uid=1001(roaima) gid=1001(roaima) groups=1001(roaima)
    24(cdrom)
    25(floppy)
    ...
    822413650 (international (uk) location)

그룹번호와 이름을 괄호로 구분하고 싶어서 이렇게 표현을 확장했어요

id roaima | sed -e 's/,/\n\t/g' -e '2,$s/(/ (/'

그러나 처음에 예상했던 대로 진행되지는 않았습니다. 두 번째 표현은 효과가 없는 것 같습니다.

대신 원하는 결과를 얻으려면 sed다음과 같은 두 개의 개별 명령을 실행해야 합니다.

id roaima | sed -e 's/,/\n\t/g' | sed '2,$s/(/ (/'
uid=1001(roaima) gid=1001(roaima) groups=1001(roaima)
    24 (cdrom)
    25 (floppy)
    ...
    822413650 (international (uk) location)

sed여러 지침이 포함된 하나의 명령 대신 하나의 파이프라인에 두 개의 명령이 필요한 이유는 무엇입니까 ? 아니면 하나로 이 작업을 수행할 수 있다면 sed어떻게 해야 합니까?

각 항목의 UID/GID 값과 대괄호 안의 이름(첫 번째 행의 UID 및 GID 포함) 사이에 공백이 필요하지만 실제 데이터에서는 그룹 이름에 괄호가 포함되어 있을 수 있습니다. 이름 자체가 엉망이 되는 것을 원하지 않습니다.

답변1

sedawk, or or 와 cut마찬가지로 각 perl -ne줄에서 한 줄씩 개별적으로 작동합니다.

sed -e code1 -e code2

실제로는 다음과 같이 실행됩니다.

while(patternspace = getline()) {
  linenumber++
  code1
  code2
} continue {print patternspace}

귀하의 code2가 2,$ s/foo/bar/다음과 같은 경우입니다.

if (linenumber >= 2) sub(/foo/, "bar", patternspace)

입력한 내용은 한 줄이므로 sub()실행되지 않습니다.

패턴 공간에 개행 문자를 삽입해도 증가 code1하지 않습니다 .linenumber

대신 처리할 때 여러 줄을 포함하는 패턴 공간이 있습니다.첫 번째그리고 입력은 한 줄만 있습니다. 여러 줄 패턴 공간의 두 번째 줄 이상을 변경하려면 다음을 수행해야 합니다.

s/\(\n[^(]*\)(/\1 (/g

물론 여기에서는 두 작업을 동시에 수행할 수도 있습니다.

id | sed 's/,\([^(]*\)(/\n\t\1 (/g'

답변2

GNU sed가 있다면 다음을 사용할 수 있습니다.

id username | sed 's/(/ (/4g; s/,/\n\t/g'

네 번째 및 후속 여는 괄호 앞에 공백을 추가한 다음 쉼표를 바꿉니다.

답변3

@stéphane-chazelas가 말한 내용은 사실이지만 언제든지 공백을 먼저 추가한 다음 다음과 같이 줄을 나눌 수 있습니다.

sed -e 's:\([,=][0-9]*\):\1 :g' -e 's:,:\n\t:g'

또는 단일 sed 스크립트에서( 없이 -e):

sed 's:\([,=][0-9]*\):\1 :g; s:,:\n\t:g'

일반적으로 " "를 명령 검색의 구분 기호로 사용 /하지만 모든 문자도 허용하므로 " "와 같은 조합을 :피하기 위해 " /\"와 같은 다른 문자를 사용하여 읽는 것이 더 쉽습니다.

관련 정보