마지막 주석 처리된 줄부터 "foo"가 있는 줄까지 모든 줄에 주석을 달았습니다.

마지막 주석 처리된 줄부터 "foo"가 있는 줄까지 모든 줄에 주석을 달았습니다.

텍스트 파일을 고려하십시오 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추악한 농담으로 만들 수 있다는 것을 알았습니다.확실히 더 깨끗한 방법이 있어야합니까?

답변1

기존 주석 줄이 연속 블록을 형성하는 경우 다음으로 시작할 수 있습니다.첫 번째대신, 아직 주석 처리되지 않은 종료 패턴까지만 주석 처리하여 행을 주석 처리하십시오.

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

기존 주석이 연속되지 않으면 sed의 범위 일치의 탐욕스러운 특성으로 인해 이와 같은 작업을 수행해야 할 것 같습니다.

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

즉 일치위로종료 모드에서 "첫 번째" 주석까지 - 내부 솔루션을 원하는 경우 이는 분명히 그리 편리하지 않습니다.

답변2

어때요?

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

답변3

단일 호출로 두 가지 경우(단일 연속 블록의 주석 처리된 줄 또는 주석 처리되지 않은 줄 사이에 배치된 줄)를 모두 처리할 수 있습니다 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기존 버퍼 에 추가하고 x버퍼를 변경한 다음 \n패턴 공간의 모든 ewline 문자를 ewline 및 ewline으로 바꿉니다(즉, 패턴 공간의 모든 라인 이제 모두 첫 번째 줄을 예약된 공간으로 포함합니다(첫 번째 줄은 항상 주석 줄입니다). 샘플이 있습니다:\n##
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부터(및 포함)까지 의 줄만 주석 처리합니다 . 물론, 이는 일치하는 line 앞에 항상 최소한 하나의 주석 행이 있다고 가정합니다 . 그렇지 않은 경우 교체하기 전에 추가 검사를 추가할 수 있습니다.dotan
PATTERN/^#/{s/\n/&#/g}

답변4

여기 또 다른 것이 있습니다 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배포하더라도 마지막 주석 처리된 이벤트를 정확하게 추적하는 데 필요한 것보다 더 많은 것을 버퍼에 유지하지 않으며 언제든지 마지막 줄을 만나면 다음을 시도합니다. 최종 g로컬 실행 문과 분기를 사용 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정말 멋지네요. 나는 이 분야에서 많은 것을 배웠다.

관련 정보