한 곳에 바이너리가 아닌 파일의 대규모 컬렉션이 있습니다. 그 중 일부는 셔뱅이 있고 일부는 (설명할 수 없는 이유로) 셔뱅 앞에 공백이 있습니다. 여기에는 다음이 포함됩니다빈 줄과 공백만 있는 줄!
예시 1:
#!/usr/bin/env foo 바
예 2:
#!/usr/bin/env foo 바
예시 3:
#! /bin/sh -e
예시 4:
______ /____/___ ____ / /_ / __ \/ __ \ /__/ / /_/ / /_/ / /_/ \____/\____/ 오늘의 팁을 담은 Foo 뉴스 #324입니다: 쉘 스크립트 파일 상단에 #!/bin/sh를 넣는 것을 잊지 마세요!
나는 1과 2와 같은 파일에서 선행 공백을 제거하는 동시에 3, 특히 4(shebang과 같은 내용이 포함된 경우에도)를 유지하는 GNU(Linux) 기반 시스템을 위한 솔루션을 기대하고 있습니다.
예제 1과 2는 다음과 같습니다.
#!/usr/bin/env foo 바
지금까지 실패한 시도는 다음과 같습니다.
첫 번째 단계는 예제 1-3과 4를 구별하는 것입니다.
grep -Pzo '^[ \t\n]+#! ?[ \w/.-]+'
때문에 작동하지 않습니다
grep: unescaped ^ or $ not supported with -Pz
.사용
awk
:awk 'BEGIN {ws_check=1} !/[ \t]+/ {ws_check=0} /#! ?[ \w/.-]+/,0 && ws_check { print }'
예제 4를 감지하고 shebang을 사용하여 나머지는 다듬지 않고 왼쪽 다듬기 선의 일부만 인쇄하려면 아직 해야 할 일이 많습니다.
답변1
perl
파일을 메모리에 넣고 파일에서 공백이 아닌 첫 번째 문자가 shebang인 경우에만 선행 공백을 제거합니다.
perl -i.bak -0pe 's/^\s+(?=#!)//' file
또는 많은 파일의 경우:
for f in ./*; do perl -i.bak -0pe 's/^\s+(?=#!)//' "$f"; done
이것은(?=#!)
긍정적 인 전망이므로 대체 연산자는 파일 시작 부분에 있는 공백(줄바꿈 및 탭 포함)만 제거하고 #!
. 이렇게 하면 -i.bak
만일의 경우에 대비해 수정된 모든 파일의 백업을 유지할 수 있습니다. 예상대로 작동한다고 확신한다면 yes 입니다 rm *.bak
.
여기에 사용되는 옵션은 perl
다음과 같습니다.
-0
: 입력 레코드 구분 기호($/
)를 8진수 또는 16진수로 지정합니다.-0
단독으로 사용하면perl
파일이 단순해지고 기본적으로 한 줄로 처리됩니다. *-i.bak
: nplace 파일을 편집i
하고 확장자가.bak
.-p
: 입력 파일을 한 줄씩 처리하고, 주어진 스크립트를 적용한 후 각 줄을 인쇄합니다-e
.-e
: 실행할 스크립트를 명령줄 인수로 전달합니다.
답변2
perl -i -p -e 'if ($. == 1) {s/^\s+#!/#!/}' *
이렇게 하면 각 파일의 #!
첫 번째 줄( ) 앞의 공백 만 제거됩니다. $. == 1
다른 모든 라인은 수정 없이 통과되었습니다. perl
파일은 변경 사항이 발생했는지 여부에 관계없이 업데이트됩니다(즉, 새 inode가 있고 타임스탬프가 업데이트됩니다). 자세한 내용은 man perlrun
두 번째 항목을 확인 하고 검색하세요.)-i\[
#! 앞에 잘못된 공백이 있는 파일만 수정(타임스탬프, inode 등 변경)하려는 경우 다음을 시도하십시오.
awk '/^[[:blank:]]+#!/ && FNR==1 { printf "%s\0", FILENAME }; {nextfile}' * |
xargs -0r perl -i -p -e 'if ($. == 1) {s/^\s+#!/#!/}'
awk
NUL로 구분된 일치하는 파일 목록을 출력합니다(첫 번째 줄에는 #! 앞에 공백이 있습니다). 이는 한 줄의 코드를 실행하기 위해 xargs -0r
입력 됩니다.perl
이 nextfile
기능에는 GNU가 필요합니다 awk
. 다른 버전에서는 생략할 수 있지만 awk
실행 속도가 느려집니다(첫 번째 줄을 확인한 후 다음 파일로 점프하는 대신 모든 파일의 모든 줄을 읽어야 하기 때문입니다).
이 작업은 에서 완전히 수행될 수 있지만, 이렇게 하려면 출력을 파이핑하는 perl
것보다 더 많은 코드가 필요합니다 .awk
xargs perl