마지막으로 주석이 달린 줄부터 'foo'로 줄을 모두 주석 처리하십시오.


12

텍스트 파일을 고려하십시오 users.txt.

#alice
#bob
charlie
dotan
eric

마지막 주석 행부터 (포함)까지 모든 것을 주석 처리해야합니다 dotan. 결과는 다음과 같습니다.

#alice
#bob
#charlie
#dotan
eric

sed이것을 할 수 있는 멋진 oneliner가 있습니까? sed실제로 는 물론 모든 도구에 만족할 것입니다.

현재 마지막으로 주석 처리 된 줄의 줄 번호를 얻습니다.

$ cat -n users.txt | grep '#' | tail -n1
  2 #bob

그런 다음 하나를 추가하고 주석을 추가하십시오 sed.

$ sed -i'' '3,/dotan/ s/^/#/' users.txt

나는 영리하고이 모든 bc것들을 추악한 라이너로 만들 수 있다는 것을 알고 있습니다 . 분명 더 깨끗한 방법이 있어야합니까?

답변:


5

어때요?

perl -pe '$n=1 if s/^dotan/#$&/; s/^[^#]/#$&/ unless $n==1;' file

또는 awk의 동일한 아이디어 :

awk '(/^dotan/){a=1; sub(/^/,"#",$1)} (a!=1 && $1!~/^#/){sub(/^/,"#",$1);}1; ' file

7

기존 주석 처리 된 행이 하나의 연속 된 블록을 형성하는 경우, 첫 번째 주석 처리 된 행 과 일치시킬 수 있으며, 아직 주석 처리되지 않은 종료 패턴을 포함하여 해당 행만 주석 처리 할 수 ​​있습니다.

sed '/^#/,/dotan/ s/^[^#]/#&/' file

기존 의견이 인접하지 않은 경우 sed 범위 일치의 탐욕스러운 특성으로 인해 다음과 같은 작업을 수행해야한다고 생각합니다.

tac file | sed '/dotan/,/^#/ s/^[^#]/#&/' | tac

즉 , 최종 패턴에서 '첫 번째'주석까지 위쪽으로 일치 시킵니다. 물론 적절한 솔루션을 원한다면 그렇게 편리하지 않습니다.


4

한 번의 sed호출로 두 경우 (단일 연속 블록에서 주석 처리 된 행 또는 주석 처리되지 않은 행에 산재 된)를 처리 할 수 ​​있습니다 .

sed '1,/PATTERN/{/^#/{x;1d;b};//!{H;/PATTERN/!{1h;d};//{x;s/\n/&#/g}}}' infile

1,/PATTERN/범위 내의 라인 만 처리합니다 . 그것은 전자 x의 변화가 w 공간을 누릅니다. 행이 주석 처리 될 때마다 패턴 공간 (따라서 보류 버퍼에 주석 처리 된 행이 두 개 이상 존재하지 않음)하고 H이전 공간에 주석 처리되지 않은 모든 행을 추가 합니다 (첫 번째 행에있을 때 1d각각 1h초기 행을 제거해야 함) 홀드 버퍼의 빈 줄).
PATTERN과 일치하는 행에 도달하면 H이전 버퍼 에도 추가하고 , e x는 버퍼를 변경 한 다음 \n패턴 공간의 모든 ewline 문자를 \newline과 a 로 바꿉니다 #(즉, 패턴 공간의 모든 행은 이제 #, 보류 공간에서 첫 번째 행으로 첫 번째 행을 포함하는 것은 항상 주석 처리 된 행입니다).
샘플 infile:

alice
#bob
bill
#charlie
ding
dong
dotan
jimmy
#garry

달리는:

sed '1,/dotan/{                   # if line is in this range    -start c1
/^#/{                             # if line is commented        -start c2
x                                 # exchage hold space w. pattern space
1d                                # if 1st line, delete pattern space
b                                 # branch to end of script
}                                 #                             -end c2
//!{                              # if line is not commented    -start c3
H                                 # append to hold space
/dotan/!{                         # if line doesn't match dotan -start c4
1h                                # if 1st line, overwrite hold space
d                                 # delete pattern space
}                                 #                             -end c4
//{                               # if line matches dotan       -start c5
x                                 # exchage hold space w. pattern space
s/\n/&#/g                         # add # after each newline character
}                                 #                             -end c5
}                                 #                             -end c3
}' infile                         #                             -end c1

출력 :

alice
#bob
bill
#charlie
#ding
#dong
#dotan
jimmy
#garry

그래서 그것은 (그리고 제외)에서 ( #charlie포함하는) 줄까지 주석 처리 dotan하고 다른 줄은 그대로 둡니다.
물론 이것은 일치하는 줄 앞에 항상 적어도 하나의 주석 처리 된 줄이 있다고 가정합니다 PATTERN. 그렇지 않은 경우 교체 전에 추가 검사를 추가 할 수 있습니다./^#/{s/\n/&#/g}


감사합니다.이 답변에서 배울 점이 꽤 있습니다!
dotancohen

잠깐만 요. 이것은 관하여이지 않는다 마지막으로 주석 라인의 시리즈? 아뇨, 알아요 마지막 시리즈 + 도탄. 꽤 영리한.
mikeserv

1
항상 최고의 질문을 찾으십시오. 저주받은 도탄은 잠시 동안 나를 던졌습니다. 아마도 그래요, 아직 테스트하지 않았습니다. 고마워요
mikeserv

2

다른 하나는 다음과 같습니다 sed.

sed  -e:n -e'/\n#.*\ndotan/!{$!{N;/^#/bn'      \
-eb  -e\} -e'/^#/s/\(\n\)\(dotan.*\)*/\1#\2/g' \
-et  -e\} -eP\;D <in >out

그것은 당신이 요구 한대로합니다. 주석 처리 된 행의 발생 사이에 필요할 때와 필요한 한 오랫동안 빌드하고 새로운 주석 처리 된 행을 찾기 위해 이전 버퍼를 입력 할 때 입력에서 추가로 덤프합니다. 그림...

여기에 이미지 설명을 입력하십시오

죄송하지만 왜 그런지 모르겠습니다. 그러나 그것은 생각났다.

어쨌든 sed어떤 시리즈의 마지막 주석이 달린 행 사이에 버퍼를 펼치고 마지막 주석이 발생한 것을 정확하게 추적하는 데 필요한 것보다 버퍼에 하나 이상의 버퍼를 유지하지 않으며 언제든지 마지막 행이 발생하면 시도합니다. 최종 gLobal 실행 명령문과 t전체 버퍼가 인쇄되도록 분기 합니다. 그렇지 않으면 P버퍼에서 해제되는 모든 라인이 즉시 인쇄됩니다.

나는 이것이 아코디언을 생각하게 한 것 같아 ...

printf %s\\n   \#alice \#bob charlie dotan eric \
               \#alice \#bob charlie dotan eric \
               \#alice \#bob charlie dotan eric |
sed  -e:n -e'l;/\n#.*\ndotan/!{$!{N;/^#/bn'     \
-eb  -e\} -e'/^#/s/\(\n\)\(dotan.*\)*/\1#\2/g'  \
-et  -e\} -eP\;D

#alice
#alice\n#bob$
#alice\n#bob\ncharlie$
#alice\n#bob\ncharlie\ndotan$
#alice
#bob\ncharlie\ndotan$
#bob\ncharlie\ndotan\neric$
#bob\ncharlie\ndotan\neric\n#alice$
#bob\ncharlie\ndotan\neric\n#alice\n#bob$
#bob\ncharlie\ndotan\neric\n#alice\n#bob\ncharlie$
#bob\ncharlie\ndotan\neric\n#alice\n#bob\ncharlie\ndotan$
#bob
charlie\ndotan\neric\n#alice\n#bob\ncharlie\ndotan$
charlie
dotan\neric\n#alice\n#bob\ncharlie\ndotan$
dotan
eric\n#alice\n#bob\ncharlie\ndotan$
eric
#alice\n#bob\ncharlie\ndotan$
#alice
#bob\ncharlie\ndotan$
#bob\ncharlie\ndotan\neric$
#bob\ncharlie\ndotan\neric\n#alice$
#bob\ncharlie\ndotan\neric\n#alice\n#bob$
#bob\ncharlie\ndotan\neric\n#alice\n#bob\ncharlie$
#bob\ncharlie\ndotan\neric\n#alice\n#bob\ncharlie\ndotan$
#bob
charlie\ndotan\neric\n#alice\n#bob\ncharlie\ndotan$
charlie
dotan\neric\n#alice\n#bob\ncharlie\ndotan$
dotan
eric\n#alice\n#bob\ncharlie\ndotan$
eric
#alice\n#bob\ncharlie\ndotan$
#alice
#bob\ncharlie\ndotan$
#bob\ncharlie\ndotan\neric$
#bob
#charlie
#dotan
eric

이 명령과 위의 명령 사이에는 하나의 차이점 만 l있으며 맨 위 의 ook 명령입니다. 우리가 작동하는 패턴 공간을 l살펴보면 sed장면 뒤에서 일어나는 일에 대한 더 나은 아이디어와 노력을 지시하는 방법에 대한 더 나은 이해를 얻을 수 있습니다.

이 경우 sed두 번째 입력이 발견 될 때까지 스택 입력을 볼 수 있으며 \n#.*\ndotan, 한 번에 한 줄씩 이전 출력을 인쇄 할 때이를 볼 수 있습니다. 좀 멋지다. 나는 이것에 대해 많은 것을 배웠다.


아주 좋습니다 감사 해요! 설명이있는 마지막 단락은 훌륭합니다.이 게시물에서 배우는 데 꽤 많은 시간을 할애합니다. 좋은 스택!
dotancohen

1
@dotancohen-이것은 정말 좋은 질문이었습니다. 스택 을 보려면 편집 내용을 살펴보십시오 .
mikeserv

2
편집 내역에 항목이 표시 Handle many dotans됩니다. 이것이 제 아내의 최악의 악몽이라고 확신합니다.
dotancohen

1
@dotancohen-예, 이것은 힘든 일이었습니다. 물건 등 #\ndotan\ndotan이러한 것들에 대한 어렵다. 나는 이것이 좋은 질문이라고 말할 때 그것을 의미합니다. 나는 생각 난 그냥 완벽한 대해 그것을 가지고,하지만 한 가지 문제 귀하의 코멘트 블록이 1000 명 선으로 분리하는 경우에 실행이다 - 그 을 늦출. 예를 들어 버퍼가 150 줄에 걸쳐있는 경우 먼저 버퍼를 분리 s/\n/&/150;t하기 전에 비슷한 것을 고수 할 수 있습니다 /\n#. 어쨌든, 어쩌면 그녀가 기다리고 있었는지 그냥 모두 함께 !
mikeserv
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.