tr -c \\n 1 <testfile | #first transform every [^\n] char to a 1
grep -nF '' | #next get line numbers
paste -d: - testfile | #then paste it together with itself
sort -t: -nk2,2 #then sort on second field
... 그리고 우승자는 ... 2 번 줄입니다.
2:1111:4for
4:11111:five!
1:1111111:seven/7
3:11111111:8 eight?
그러나 문제는 모든 라인의 길이가 두 배 이상 길어야 LINE_MAX 가 효과적으로 반감 된다는 것 입니다. 원인은 그것이 무엇을 사용하고 있기 때문입니다-무엇, 기본 1? -선의 길이를 나타냅니다. 비슷하고 더 깔끔한 접근 방식은 해당 정보를 스트림으로 압축하는 것입니다. 나에게 나타나는 선을 따르는 첫 번째 아이디어는 내가해야한다는 unexpand
것입니다.
tr -c \\n \ <testfile | #transform all [^\n] to <space>
unexpand -t10 | #squeeze every series of 10 to one tab
grep -nF '' | #and get the line numbers
sed 's/:/!d;=;:/;h;:big #sed compares sequential lines
$P;$!N; /\(:[^ ]*\)\( *\)\n.*\1.*\2/!D #newest line is shorter or...
g;/:./!q;b big' | #not; quit input entirely for blank line
sed -f - -e q testfile #print only first occurrence of shortest line
그 인쇄 ...
2
4for
또 다른 하나 sed
:
sed -n '/^\n/D;s/\(.\)\(\n.*\)*/\1/g
$p;h; s// /g;G;x;n;//!g;H;s// /g
G; s/^\( *\)\(\n \1 *\)\{0,1\}\n//
D' <infile >outfile
이 구문은 표준을 준수하지만 오래된 sed
것이 \(reference-group\)\{counts\}
올바르게 처리 된다는 보장 은 없습니다.
기본적으로 동일한 정규 표현식을 반복적으로 입력에 적용하므로 컴파일 할 때 매우 유용합니다. 그 패턴은 다음과 같습니다
\(.\)\(\n.*\)*
다른 방식으로 다른 문자열과 일치합니다. 예를 들면 다음과 같습니다.
string1\nstring2\nstring3
...과 일치 s
에 \1
와 ''
있는 널 (null) 문자열 \2
.
1\nstring2\nstring3
...과 일치 1
의 \1
및 \nstring2\nstring3
의\2
\nstring2\nstring3
...과 일치 \n
에 \1
와 ''
있는 널 (null) 문자열 \2
. \n
패턴 공간의 헤드에서 ewline이 발생할 가능성이있는 경우 문제가 될 수 있지만, 이를 방지하기 위해 /^\n/D
, 및 //!g
명령이 사용됩니다. 나는 [^\n]
이 작은 스크립트에 대한 다른 요구를 사용 하여 이식성을 염려했으며 종종 잘못 해석되는 많은 방법에 만족하지 못했습니다. 게다가 .
빠릅니다.
\nstring2
string1
... 일치 \n
하고 s
다시 \1
그리고 둘 다에서 ''
null 문자열을 가져옵니다 \2
. 빈 줄이 전혀 일치하지 않습니다.
패턴이 g
전체적으로 적용되는 경우 , 가장 왼쪽의 표준 바이어스와 오른쪽의 오른쪽 \n
ewline 바이어스 모두 두 개의 바이어스 가 카운터 밸런스되어 스킵됩니다. 몇 가지 예 :
s/\(.\)\(\n.*\)*/\1:\2/g
s/\(.\)\(\n.*\)*/\2\1:/g
s/\(.\)\(\n.*\)*/\1: /g
s/\(.\)\(\n.*\)*/ :\2/g
... 다음 문자열 에 모두 가 연속으로 적용 되지 않는 경우 ...
string1\nstring2
... 그것을 ...
s:t:r:i:n:g:1:\nstring2
s:t:r:i:n:g:\nstring21:
s:t:r:i:n:g:1:
: : : : : : :\nstring2
기본적으로 나는 정규 표현식을 사용하여 항상 적용 할 패턴 공간의 첫 번째 줄만 처리합니다. 이를 통해 루프 테스트에 의존하지 않고 가장 짧은 유지 일치 라인과 가장 최근 라인의 두 가지 버전을 저글링 할 수 있습니다. 적용된 모든 대체는 전체 패턴 공간을 한 번에 처리합니다.
리터럴 문자열 / 문자열 비교에는 다른 버전이 필요하므로 모든 문자가 동일하게 보장되는 각 행의 버전이 있어야합니다. 그러나 물론 하나 또는 다른 하나가 실제로 가장 짧은 입력 라인에서 실제로 감기면 출력으로 인쇄 된 라인은 아마도 비교를 위해 위생 처리 / 균질화 된 라인이 아닌 원래 버전의 라인이어야합니다. 그래서 나는 두 가지 버전이 필요합니다.
불행히도 또 다른 필요성은 동일한 것을 처리하기 위해 많은 버퍼 전환이 필요합니다. 그러나 적어도 어느 버퍼도 전류를 유지하는 데 필요한 4 라인 이상을 초과하지 않으므로 끔찍하지 않을 수도 있습니다.
어쨌든, 각주기마다 가장 먼저 발생하는 일은 기억 된 줄의 변형입니다. 실제로 저장된 유일한 사본은 리터럴 원본이므로 ...
^ \nremembered line$
... 그리고 나서 n
ext 입력 라인은 오래된 버퍼를 덮어 씁니다. 하나 이상의 문자를 포함하지 않으면 효과적으로 무시됩니다. q
처음 나타나는 빈 줄 에 맞추는 것이 훨씬 쉽지만 테스트 데이터에는 많은 양이 있었고 여러 단락을 처리하고 싶었습니다.
따라서 문자가 포함되어 있으면 리터럴 버전이 기억 된 행에 추가되고 간격 비교 버전은 다음과 같이 패턴 공간의 헤드에 배치됩니다.
^ \n \nremembered line\nnew$
마지막으로 해당 패턴 공간에 대체가 적용됩니다.
s/^\( *\)\(\n \1 *\)\{0,1\}\n//
따라서 줄 바꿈이 기억할 줄을 포함하는 데 필요한 공간에 하나 이상의 문자를 포함하는 데 필요한 공간에 들어가면 처음 두 줄만 대체됩니다.
결과에 관계없이 패턴 공간의 첫 번째 라인은 D
다시 시작하기 전에 항상 사이클 끝에서 엘레 트됩니다. 이것은 새 줄이 마지막 줄보다 짧으면 ...
new
... 첫 번째 줄 바꿈 문자에서만 항상 제거되는 사이클의 첫 번째 대체로 다시 전송되므로 전체가 유지됩니다. 그러나 그것이 문자열이 아니면 ...
remembered line\nnew
... 다음 사이클을 시작하고 첫 번째 치환은 문자열에서 제거합니다 ...
\nnew
... 매번.
마지막 줄에서 기억 된 줄은 표준 출력으로 인쇄되므로 주어진 예제 데이터의 경우 다음과 같이 인쇄됩니다.
4for
그러나 진지하게 사용하십시오 tr
.