다른 문자열 다음에 #으로 시작하는 문자열을 이전 줄로 이동할 수 있습니까?

다른 문자열 다음에 #으로 시작하는 문자열을 이전 줄로 이동할 수 있습니까?

다음과 같은 스크립트 파일이 있습니다.

auditctl -a always,exit -F arch=b64 -S openat -F auid=1000      <TAB> #description of command....
auditctl -a ....                                                <TAB> #long description

(주석 앞의 탭 문자에 유의하세요.)

, 또는 sed내부 명령을 사용하여 문자열 자체 뒤에 설명을 넣을 수 있으므로 다음과 같은 결과가 나타납니다.awkvim#

#description of command....
auditctl -a always,exit -F arch=b64 -S openat -F auid=1000      


#long description
auditctl -a ....

이 명령을 시도했지만 norm결과는 재앙이었습니다.

:'<,'>norm f#D O P

답변1

match()GNU awk를 세 번째 인수 및 \S/\s약어 로 사용합니다 .

$ awk 'match($0,/([^#]*\S)\s*(#.*)/,a) { $0=a[2] ORS a[1] } 1' file
#description of command....
auditctl -a always,exit -F arch=b64 -S openat -F auid=1000
#long description
auditctl -a ....

또는 POSIX awk를 사용하십시오.

$ awk 'match($0,/[[:space:]]*#/) { $0=substr($0,RSTART+RLENGTH-1) ORS substr($0,1,RSTART-1) } 1' file
#description of # command....
auditctl -a always,exit -F arch=b64 -S openat -F auid=1000
#long description
auditctl -a ....

위 의 #코드는 주석에 포함된 문자( a 포함)와 주석 앞에 공백이 있는지 여부에 관계없이 작동하며 인쇄하기 전에 나머지 줄 끝에서 주석 전 공백을 모두 제거합니다.

답변2

를 사용하면 sed역참조를 사용하여 패턴을 일치시킬 수 있습니다.

sed 's/\(PATTERN1\)\(PATTERN2\)/\2\n\1/'

두 패턴을 반전시키고 그 사이에 개행 문자를 추가합니다. 예를 들어 PATTERN1은 ^.*줄의 시작 부분부터 시작하는 모든 문자일 수 있고, PATTERN2는 #.*$줄 끝까지의 임의 개수의 문자가 뒤에 오는 해시 기호일 수 있습니다.

추가 공백을 제거하려면 다음을 추가해야 할 수도 있습니다.

's/ *$//'

#일치의 첫 번째 부분에서 문자(즉, NOT이 아닌 모든 문자)를 제외하여 [^#]자신의 텍스트에서 주석을 처리하는 것도 좋은 생각입니다 #. 결합하면 다음과 같습니다.

sed 's/\(^[^#]*\)\(#.*$\)/\2\n\1/;s/ *$//'

답변3

다음 awk프로그램은 다음을 수행해야 합니다.

awk '/^ *[^ #].+#/{n=index($0,"#"); print substr($0,n); $0=substr($0,1,n-1)}1' input.sh

이렇게 하면 다음이 수행됩니다.

  • 우리는 첫 번째 문자(아마도 선행 공백 뒤)가 있는 행만 처리하는지 확인합니다.아니요기호 #, 즉 "일반 주석" 줄이 아닌 명령 뒤의 주석인지 확인하세요.
  • 이와 같은 줄에 있다면 첫 번째 줄의 위치를 ​​결정하여 #에 저장합니다 n. 그런 다음 해당 위치에서 시작하여 현재 줄의 하위 문자열을 별도의 줄에 인쇄합니다. 그런 다음 현재 줄을 #. 이 접근 방식은 #주석 섹션 자체에 해당 문자가 포함된 경우도 처리합니다.
  • 1모든 행에 대해 수정되었을 수 있는 내용을 포함하여 인쇄합니다(이것은 규칙 블록 외부에서 "빠진" 것으로 나타납니다).

awk파일의 내부 편집을 수행하지 않으므로 출력을 임시 파일로 리디렉션해야 합니다 . 또는 GNU Awk 4.1.0 이상이 있는 경우 -i inplace진정한 내부 편집을 위해 이 확장을 사용할 수 있습니다.

답변4

rev@Ed Morton이 지적한 대체 사례와 같은 이 접근 방식이 마음에 듭니다 .

입력 파일 예:

auditctl -a always,exit -F arch=b64 -S openat -F auid=1000      #description of command....
auditctl -a ....                                                #long description
auditctl -a always,exit -F arch=b64 -S openat -F auid=1000#description of command....
auditctl -a ....                                                #long description# foo
auditctl -a ....                                                # long description#foo
$ rev file | sed 's/^\(.*\)#[[:blank:]]*/\1#\n/' | rev
#description of command....
auditctl -a always,exit -F arch=b64 -S openat -F auid=1000
#long description
auditctl -a ....
#description of command....
auditctl -a always,exit -F arch=b64 -S openat -F auid=1000
#long description# foo
auditctl -a ....
# long description#foo
auditctl -a ....

관련 정보