원격 저장소에 커밋하기 전에 일부 자동 서식을 개선하기 위해 자체 스크립트를 작성하려고 합니다. 내 IDE에서 들여쓰기 가이드를 사용하고 있는데 내 언어의 자동 포맷터(FORTRAN)가 빈 줄 들여쓰기를 지원하지 않습니다. 내가 본질적으로 원하는 것은 sed
파일의 줄을 반복하고 줄이 비어 있으면 줄과 동일한 수의 공백이 생길 때까지 줄에 공백을 추가하는 것입니다.그 위에(따라서 첫 번째 줄은 무시하십시오). 이것을 커밋 전 후크의 일부로 사용하고 싶기 때문에 파일이 요구 사항을 통과하고 수정되지 않았다면 좋을 것입니다.
공백 이 해당하는 형식화되지 않은 파일의 예 >
:
Start of document - First line is ignored
Second line has text and is therefore ignored
>>>>Third line has four spaces so below (empty line) should have 4 spaces added.
>>>>>>>>Third line has 8 spaces so below (empty line) should have 8 spaces added.
End of document
원하는 출력:
Start of document - First line is ignored
Second line has text and is therefore ignored
>>>>Third line has four spaces so below (empty line) should have 4 spaces added.
>>>>
>>>>>>>>Third line has 8 spaces so below (empty line) should have 8 spaces added.
>>>>>>>>
End of document
그리고 이와 관련하여 느낌표로 시작하는 줄을 들여쓰고 싶습니다.열 1에(앞의 공백 없이) 위 줄 수준으로 이동합니다(왜냐하면 내가 사용하는 자동 포맷터가 이를 지원하지 않기 때문입니다).
공백 이 해당하는 형식화되지 않은 파일의 예 >
:
Start of document - First line is ignored
! Second line starts with exclamation mark in column 1 so it is indented to level of above line
>>>>Third line has 4 spaces to start
!This should have 4 spaces added to it because the first character is ‘!’ and above line has 4
>>>>>>>>This line has 8 spaces
>>>>>>>>!This line shouldn’t be changed as it begins with a space, not an exclamation mark.
End of document
원하는 출력:
Start of document - First line is ignored
! Second line starts with exclamation mark in column 1 so it is indented to level of above line
>>>>Third line has 4 spaces to start
>>>>!This should have 4 spaces added to it because the first character is ‘!’ and above line has 4
>>>>>>>>This line has 8 spaces
>>>>>>>>!This line shouldn’t be changed as it begins with a space, not an exclamation mark.
End of document
저는 bash 스크립팅을 처음 접했기 때문에 솔루션 작동 방식에 대한 설명이 훌륭할 것이며 도움을 주셔서 미리 감사드립니다!
편집: 댓글에서 요청한 대로 이미지를 텍스트로 대체했습니다!
답변1
사용 sed
:
sed -n \
-e '/^!/ { G; s/\(.*\)\n\(.*\)/\2\1/; }' \
-e '/^$/g' \
-e p \
-e 's/^\( *\).*/\1/' \
-e h file
이는 일련의 sed
편집 표현식을 사용하여 원하는 들여쓰기를 수행합니다. 스크립트는 예약된 공간( 의 편집 불가능한 보조 버퍼 sed
)을 사용하여 현재 들여쓰기를 여러 공백 문자로 저장합니다.
!
줄의 첫 번째 위치가 a로 시작하면 첫 번째 표현식이 트리거됩니다. 이 표현식은 개행 문자를 구분 기호로 사용하여 예약된 공간에 있는 내용을 현재 행의 끝에 추가한 다음 버퍼의 두 부분을 교환하여 개행 문자를 제거합니다. !
현재 들여쓰기 수준으로 -line을 들여쓰기 합니다 .
두 번째 표현식은 빈 줄에 대해 실행되고 예약된 공간에 있는 내용으로 대체됩니다. 빈 줄에 적절한 양의 공백을 추가하는 역할을 합니다.
세 번째 표현식은 편집 버퍼의 현재 내용을 출력합니다. 현재 올바르게 들여쓰기되어 있으므로(-line !
, 빈 줄 또는 아직 수정하지 않은 다른 줄로 인해) 이를 명시적으로 수행하고 나머지 부분을 처리할 수 있도록 곧 수정해야 합니다. 문서를 올바르게.
마지막 두 작업은 공백 들여쓰기 끝에서 현재 줄을 자른 다음 루프를 통해 다음 번에 사용할 수 있도록 나머지 들여쓰기를 예약된 공간에 저장합니다. 예를 들어 [[:blank:]]
탭이나 공백을 사용하여 들여쓰기와 일치 하도록 마지막 교체의 공백을 바꿉니다 .
답변2
이와 같은 작업은 awk
또는 같은 언어에서 가장 잘 수행 됩니다 perl
(sed에는 변수가 없으므로).
다음 한 줄의 Perl 코드는 두 요구 사항 모두에 적합합니다. 필요한 줄의 시작 부분에 공백이 추가되어 각 줄의 끝을 나타내는 cat -A
것을 볼 수 있도록 출력을 파이프로 연결했습니다 .$
첫 번째 명령문은 변수의 내용을 $spaces
행의 시작 부분( )에 추가합니다. $_
행이 비어 있거나 !
첫 번째 입력 행에서 -로 시작하면 $spaces
비어 있게 됩니다 . 두 번째 문은 현재 줄(있는 경우)의 시작 부분에 있는 공백을 캡처하여 $spaces
다음 입력 줄에서 사용할 수 있도록 준비합니다.
참고: 여기서 사용된 은 \h
가로 공백(ASCII 파일의 공백과 탭 및 일부 유니코드 공백 문자)을 의미합니다. 공백 문자만 사용하려면 \h
단일 공백으로 변경하세요: ($spaces) = (/^( *)/)
.
첫 번째 입력 파일:
$ perl -p -e 'if (/^($|!)/) { $_ = $spaces . $_ };
($spaces) = (/^(\h*)/)' input1.txt | cat -A
Start of document - First line is ignored$
Second line has text and is therefore ignored$
Third line has four spaces so below (empty line) should have 4 spaces added.$
$
Third line has 8 spaces so below (empty line) should have 8 spaces added.$
$
End of document$
두 번째 파일:
$ perl -p -e 'if (/^($|!)/) { $_ = $spaces . $_ };
($spaces) = (/^(\h*)/)' input2.txt | cat -A
Start of document - First line is ignored$
! Second line starts with exclamation mark in column 1 so it is indented to level of above line$
Third line has 4 spaces to start$
!This should have 4 spaces added to it because the first character is '!' and above line has 4$
This line has 8 spaces$
!This line shouldn't be changed as it begins with a space, not an exclamation mark.$
End of document$
또한 참고: 이는 파일(수정 여부에 관계없이)을 표준 출력으로 인쇄합니다. 원본 파일을 수정하려면 -i
명령줄에 perl 옵션을 추가하세요. 이는 sed
perl -i
옵션과 유사합니다. 자세한 내용 확인 man perlrun
및 검색 -i\[extension\]
) - 다음 사항에 특히 주의하시기 바랍니다.
-i
동일한 이름의 새 파일을 만들기 전에 원본 파일의 이름이 바뀌거나 삭제되므로 Unix 스타일 소프트 링크와 하드 링크는 유지되지 않습니다 .
git
파일의 inode 번호가 변경되더라도 내용이 변경된 경우에만 신경 쓰지 않는 것 같습니다. 그러나 하드 링크를 유지해야 하거나 입력 파일이 아직 변경되지 않은 경우 덮어쓰고 싶지 않은 경우 리디렉션하십시오. 임시 파일에 저장하고 임시 파일이 다른 경우 diff
에만 덮어씁니다.cmp