나는 코드를 가지고있다:
1 /**
2 a b c
3 **/
4 int main() {
5 int x;
6 if ( condition) {
7 return x;
8 }
9 }
7행처럼 토큰이나 문자열 사이의 여러 공백을 단일 공백으로 변경해야 하지만 주석(2행)이나 코드의 선행 탭은 영향을 받아서는 안 됩니다. 따라서 출력은 다음과 같아야 합니다.
1 /**
2 a b c
3 **/
4 int main() {
5 int x;
6 if ( condition) {
7 return x;
8 }
9 }
'tr'을 사용해 보았지만 ~$ tr -s " " < file
2행이 변경되고 5~8행에서 선행 탭 문자가 제거되었습니다. 을 사용하여 수행할 수 있습니까 sed
?
답변1
얼마나 멀리 갈 것인가?
sed -rn '\#/\*\*#,\#\*\/*# {p;b}; s/([^ ]) +/\1 /g; p' file
이해합니다? 수정되지 않은 주석 줄을 인쇄하고(그러나 같은 줄의 주석 켜기/끄기를 처리할 수 없음) 스크립트의 나머지 부분을 건너뜁니다. 주석 처리되지 않은 줄의 경우 공백이 아닌 문자 뒤에 오는 여러 공백(따라서 범위를 벗어난 줄 들여쓰기)을 단일 공백으로 압축합니다.
답변2
마지막으로 이것은 나에게 효과적이었습니다.
sed -i 's/\([a-zA-Z]\+\)\( *\)\([a-zA-Z]\+\)/\1 \3/g' $1
답변3
사용행복하다(이전 Perl_6)
~$ raku -pe 's/^ [\d+ " "?] \t* \H+? <(" " ** 2..*)> / /;' file
#OR
~$ raku -pe 's/^ [\d+ " "?] \c[TAB]* \H+? <(\c[SPACE] ** 2..*)> / /;' file
위의 Raku 코드는 문자 그대로 탭( \t
or ) \c[TAB]
과 공백( " "
or \c[SPACE]
)을 구분합니다.
이러한 -pe
플래그는 자동 인쇄 기능을 사용하여 입력에서 코드를 한 줄씩 실행합니다. 정규식은 ^
문자열의 시작 부분부터 숫자를 검색하고 [\d+ " "?]
그 뒤에 0 또는 1개의 공백, 그 뒤에 선택적 탭 문자, 그 뒤에 (탐욕스럽지 않게) \H+?
하나 이상의 수평이 아닌 공백 문자, 마지막으로 2..*
2개 이상의 공백을 검색합니다. . <(
...캡처 )>
태그는 단일 공백으로 대체되는 마지막 두 개 이상의 공백을 제외하고 일치하는 모든 항목을 제거합니다.
[\d+ " "?]
줄 번호가 없으면 대괄호로 묶인 그룹이 생략됩니다. 한 줄에 하나만 바꾸기 때문에 줄 오른쪽 끝에 공백 문자가 여러 개 있으면 여러 번 실행해야 할 수도 있습니다.
입력 예:
1 /**
2 a\tb\tc
3 **/
4 int main() {
5\tint x;
6\tif ( condition) {
7\treturn x;
8\t}
9 }
예제 출력:
1 /**
2 a\tb\tc
3 **/
4 int main() {
5\tint x;
6\tif ( condition) {
7\treturn x;
8\t}
9 }
물론 위의 답변은 주석 블록의 문자가 여러 공백이 아닌 탭으로 구분되는 것을 기반으로 합니다. 아마도 가장 좋은 방법은저것이다사전 실행특히 주석 블록을 바꾸십시오.
~$ raku -pe 'state $ph; \
$ph = 1 if /^ "/**" \s* $/; \
$ph = 0 if /^ "**/" \s* $/; \
s:g/" " ** 4/\t/ if $ph == 1 ;' file
위 코드는 주석 블록 내에서만 4개의 공백을 탭 문자로 대체합니다. 각 줄이 줄 번호로 시작하는 경우 [\d+ " "?]
두 번째 및 세 번째 문의 대괄호 그룹에 다시 추가하세요.^
https://unix.stackexchange.com/a/701572/227738
https://docs.raku.org/언어/regexes
https://raku.org