나는 당신에게 동의 할 것 입니다 -아마도 일반적인 문제 일 것 입니다 . 그러나 일부 공용 유틸리티에는 처리 기능이 있습니다.
nl
nl예를 들어, 두 문자 섹션 구분 기호로 구분 된 대로 입력을 논리 페이지 로 분리 합니다. 한 줄에 모두 세 번 나타나는 것은 제목 의 시작 , 두 번은 본문 , 한 번은 바닥 글을 나타냅니다 . 입력에서 찾은 모든 것을 출력의 빈 줄로 바꿉니다.-d
다른 섹션을 포함 시키도록 예제를 변경했습니다 ./infile. 따라서 다음과 같이 보입니다.
line A
line B
@@inline-code-start
line X
line Y
line Z
@@inline-code-end
line C
line D
@@start
line M
line N
line O
@@end
그런 다음 다음을 실행했습니다.
sed 's/^@@.*start$/@@@@@@/
s/^@@.*end$/@@/' <infile |
nl -d@@ -ha -bn -w1
nl논리 페이지에서 상태 를 누적 하도록 지시 할 수 있지만 기본적으로는 그렇지 않습니다. 대신 스타일 과 섹션 에 따라 입력 행의 번호를 지정합니다 . 따라서 본문 상태 에서 시작하므로 -ha모든 헤더 행에 번호를 매기고 본문 줄을-bn 의미 하지 않습니다 .
내가 이것을 알게 될 때까지 나는 nl모든 입력에 사용했지만 nl기본 -delimiter 에 따라 출력이 왜곡 될 수 있음을 \:깨달았을 때 더주의를 기울이고 grep -nF ''테스트되지 않은 입력을 대신 사용 하기 시작했습니다 . 그러나 다른 교훈 nl은 sed위와 같이 입력을 약간만 수정하면이와 같은 다른 측면에서 매우 유용하게 적용될 수 있다는 것을 알게되었습니다 .
산출
line A
line B
1 line X
2 line Y
3 line Z
line C
line D
1 line M
2 line N
3 line O
여기에 더 자세한 내용이 있습니다 nl-번호가있는 줄을 제외한 모든 줄이 공백으로 시작하는 방식을 알 수 있습니까? 때 nl번호 라인은 각각의 머리에 문자의 특정 번호를 삽입합니다. 해당 행의 경우 공백도 아니고 번호 가 매겨지지 않은 행의 헤드에 (idth -wcount + -separator len) * 공백을 삽입하여 들여 쓰기와 항상 일치합니다 . 이를 통해 번호가 매겨지지 않은 콘텐츠를 번호가 매겨진 콘텐츠와 비교하여 적은 노력으로 정확하게 재생할 수 있습니다. 당신이 고려해야 할 때 nl당신을 위해 논리적 인 부분으로 입력을 나누고, 그 것이다 당신은 임의 삽입 할 수있는 -s다음의 출력을 처리하기 위해 아주 쉽게 얻을 수, 각 라인이 번호의 머리에 trings를 :
sed 's/^@@.*start$/@@@@@@/
s/^@@.*end/@@/; t
s/^\(@@\)\{1,3\}$/& /' <infile |
nl -d@@ -ha -bn -s' do something with the next line!
'
위의 지문은 ...
line A
line B
1 do something with the next line!
line X
2 do something with the next line!
line Y
3 do something with the next line!
line Z
line C
line D
1 do something with the next line!
line M
2 do something with the next line!
line N
3 do something with the next line!
line O
암소 비슷한 일종의 영양 sed
nl대상 응용 프로그램이 아닌 경우 GNU sed는 e일치하는 항목에 따라 임의의 셸 명령을 실행할 수 있습니다.
sed '/^@@.*start$/!b
s//nl <<\\@@/;:l;N
s/\(\n@@\)[^\n]*end$/\1/
Tl;e' <infile
위 sed는 대체를 성공적으로 통과 하고 abel에 다시 목장을 T중지 하기에 충분할 때까지 패턴 공간에서 입력을 수집합니다 . 그렇게 할 때 , 나머지 모든 패턴 공간에 대한 여기 문서 로 표현 된 입력 값으로 xecutes 됩니다 .b:lenl<<
워크 플로우는 다음과 같습니다.
/^@@.*start$/!b
- 경우
^전체 라인은 $않습니다 !하지 /일치 /위의 패턴을, 다음이되는 b스크립트 밖으로 ranched 및 autoprinted - 그래서이 시점에서 우리는 패턴으로 시작 라인의 일련의 작업에.
s//nl <<\\@@/
- 빈
s//필드 /는 마지막으로 sed시도한 주소를 나타냅니다. 따라서이 명령 @@.*start은 nl <<\\@@대신 전체 행을 대체합니다.
:l;N
- 이
:명령은 분기 레이블을 정의합니다. 여기서 :label 이라는 이름을 설정했습니다 . NEXT 명령은 다음 패턴 공간 입력의 다음 줄에 추가 \newline 캐릭터. 이것은 패턴 공간 \n에서 ewline 을 얻는 몇 가지 방법 중 하나입니다 sed. \newline 문자는 sed잠시 동안 작업을 수행 한 사람에게 확실한 구분 기호 입니다.
s/\(\n@@\)[^\n]*end$/\1/
- 이
s///ubstitution은 시작 후에 만 났으며 엔드 라인 이 처음 나오는 경우에만 성공할 수 있습니다 . 마지막 \newline 바로 뒤에 패턴 공간의 @@.*end끝 $을 표시 하는 패턴 공간에서만 작동 합니다. 작동하면 일치하는 전체 문자열을 \1첫 번째 \(그룹 \)또는로 바꿉니다 \n@@.
Tl
T레이블로 추정 명령 지점 (제공되는 경우) 성공적으로 대체가 입력 라인 패턴의 공간으로 끌어 된 마지막 시간 이후 발생하지 않은 경우 (나는 / 승처럼 N) . 즉 \n, 끝 구분 기호와 일치하지 않는 패턴 공간에 ewline이 추가 될 때마다 Test 명령이 실패하고 :label로 분기 sed되어 N내선 을 당겨 성공할 때까지 반복됩니다.
e
마지막 줄을 편집하여 직접 확인할 수 있습니다 Tl;l;e.
다음을 인쇄합니다.
line A
line B
1 line X
2 line Y
3 line Z
line C
line D
1 line M
2 line N
3 line O
while ... read
이 작업을 수행하는 가장 마지막 방법은 아마도 가장 간단한 방법 while read이지만 루프 를 사용하는 것이지만 그럴만한 이유가 있습니다. 쉘 (특히 bash쉘) 은 일반적으로 입력을 대량으로 또는 꾸준히 처리 할 때 상당히 심합니다. 쉘의 역할은 입력 문자를 문자별로 처리하고 더 큰 것을 처리 할 수있는 다른 명령을 호출하는 것입니다.
그러나 중요한 역할은 쉘 이 입력을 과도하게 사용 해서는 read 안된다는 것입니다. 입력 또는 출력을 너무 많이 소비하거나 호출하는 명령이 부족한 시간에 충분히 릴레이하지 않는 지점까지 입력 또는 출력을 버퍼링 하지 않도록 지정합니다 -바이트에. 그래서 read훌륭한 입력있게 시험 에 - return입력 나머지가 있는지에 대한 정보 당신은 그것을 읽을 다음 명령을 호출해야합니다 -하지만 그렇지 않으면 일반적으로 이동하는 가장 좋은 방법은 아닙니다.
그러나 다음은 하나의 명령 read 과 다른 명령을 사용 하여 입력을 동기화 하는 방법에 대한 예입니다 .
while IFS= read -r line &&
case $line in (@@*start) :;; (*)
printf %s\\n "$line"
sed -un "/^@@.*start$/q;p";;
esac;do sed -un "/^@@.*end$/q;=;p" |
paste -d: - -
done <infile
각 반복에 대해 가장 먼저 발생하는 일은 read한 줄로 가져 오는 것입니다 . 성공하면 루프가 아직 EOF에 도달하지 않았으므로 시작 구분 기호 case와 일치 하면 블록이 즉시 실행됩니다. 그 밖에, 지문 을 하고 라고합니다.doprintf$linereadsed
sed것이다 p는 만날 때까지 모든 라인을 RINT 시작 이 때 - 마커를 q완전히 입력을 UITS. -unbuffered 스위치는 GNU에 대한 필요 sed가 탐욕 그렇지 않으면 오히려 버퍼 만 할 수 있기 때문에 - 사양에 따라 - 다른 POSIX sed의 특별한 고려하지 않고 작동합니다 - 너무 오래 같은 <infile일반 파일입니다.
첫 번째 sed q신호가 발생하면 쉘은 do루프 블록을 실행합니다.이 블록은 다른 블록을 호출 sed하여 끝 마커 와 마주 칠 때까지 모든 행을 인쇄 합니다. paste행 번호를 각각 자체 행에 인쇄하기 때문에 출력을로 파이프합니다 . 이처럼 :
1
line M
2
line N
3
line O
paste그런 다음 :문자 를 문자 에 붙여 넣고 전체 출력은 다음과 같습니다.
line A
line B
1:line X
2:line Y
3:line Z
line C
line D
1:line M
2:line N
3:line O
이것들은 단지 예일뿐입니다-테스트 나 do 블록에서 무엇이든 할 수 있지만, 첫 번째 유틸리티는 너무 많은 입력을 소비해서는 안됩니다.
관련된 모든 유틸리티는 동일한 입력을 읽고 결과를 인쇄합니다. 다른 유틸리티는 다른 사람보다 더 많은 버퍼 때문에 - - 이런 종류의 일이의 묘리를 터득하기 어려울 수 있지만 일반적으로 신뢰할 수있는 dd, head그리고 sed옳은 일을 (GNU에 대한,하지만 sed, 당신은 CLI 스위치 필요) 및 read본질적으로 매우 느리기 때문에 항상 의지 할 수 있어야합니다 . 이것이 위의 루프가 입력 블록 당 한 번만 호출하는 이유입니다.
nlstate 를 축적 할 필요가 없습니다 . 봐에서nl -d귀하의 확인man/info에 대한 정보는 페이지nl의 섹션 구분 기호를 .