왜`sed expr1 | `sed -e expr1 -e expr2`와 다른 sed expr2`


10

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 값과 괄호 이름 사이에 단일 공백을 두는 것입니다. 그러나주의해야 할 점은 실제 데이터에서 그룹을 가질 수 있다는 것입니다 이름에 대괄호를 포함하고 이름 자체가 엉망이되는 것을 원하지 않습니다.

답변:


14

sed, awk또는 각 라인에서 하나씩 차례로 작동 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'

awk 및 perl -n / p는 각 레코드에서 작동하며 기본값 은 한 줄이지 만 변경 될 수 있습니다. 이 경우 -vRS=,또는 -054도움 이 될 수 있습니다.
dave_thompson_085

5

GNU sed가 있다면

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

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


1
재미 있겠다. 불행히도 international (uk) location이름 자체에 원하지 않는 공간을 삽입하여 내 예와 같이 대괄호가 포함 된 그룹 이름에도 영향을 미칩니다 .
roaima

그런 다음 s/\([[:digit:]]\+\)(/\1 (/4g괄호 앞에 숫자가있는 경우에만 공백을 추가하는을 사용 하십시오.
glenn jackman

1

@ 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'

우리는 일반적으로 " /"를 명령 검색의 분리 자로 사용 하지만, 어떤 문자도 받아들이므로 " :"와 같은 조합을 피하기 위해 " " 와 같은 다른 문자를 사용하는 것이 더 쉽습니다 /\.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.