Unix 도구를 사용하여 대괄호 [] 사이의 모든 공백을 제거하는 방법은 무엇입니까? [복사]

Unix 도구를 사용하여 대괄호 [] 사이의 모든 공백을 제거하는 방법은 무엇입니까? [복사]

대괄호 사이의 텍스트 바꾸기

입력하다

testing on Linux [Remove white space] testing on Linux

산출

testing on Linux [Removewhitespace] testing on Linux

그렇다면 대괄호 사이의 모든 공백을 어떻게 제거하고 주어진 출력을 얻을 수 있습니까?

답변1

[가 균형을 이루고 중첩되지 않은 경우 다음과 같이 ]GNU를 사용할 수 있습니다 .awk

gawk -v RS='[][]' '
   NR % 2 == 0 {gsub(/\s/,"")}
   {printf "%s", $0 RT}'

즉 , 개행 대신 [및 레코드 구분 기호로 사용 하고 다른 모든 레코드에서 공백을 제거하십시오.]

sed를 사용할 때 추가 요구 사항은 내부에 개행 문자가 없어야 한다는 것입니다 [...].

sed -e :1 -e 's/\(\[[^]]*\)[[:space:]]/\1/g;t1'

균형이 잡혀 있지만 잠재적으로 다음과 같이 중첩된 경우 다음 과 같은 재귀 정규식 연산자를 blah [blih [1] bluh] asd사용할 수 있습니다 .perl

perl -0777 -pe 's{(\[((?:(?>[^][]+)|(?1))*)\])}{$&=~s/\s//rsg}gse'

(?{...})매우 큰 파일로 확장할 수 있는 또 다른 접근 방식은 다음과 같이 perl regexp 연산자를 사용하여 대괄호 깊이를 추적하는 것입니다 .

perl -pe 'BEGIN{$/=\8192}s{((?:\[(?{$l++})|\](?{$l--})|[^][\s]+)*)(\s+)}
  {"$1".($l>0?"":$2)}gse'

실제로 다음과 같이 한 번에 한 문자씩 처리할 수도 있습니다.

perl -pe 'BEGIN{$/=\1}if($l>0&&/\s/){$_=""}elsif($_ eq"["){$l++}elsif($_ eq"]"){$l--}'

이 방법은 POSIX 도구를 사용하여 구현할 수 있습니다.

od -A n -vt u1 |
  tr -cs 0-9 '[\n*]' |
  awk 'BEGIN{b[32]=""; b[10]=""; b[12]=""} # add more for every blank
       !NF{next}; l>0 && $0 in b {next}
       $0 == "91" {l++}; $0 == "93" {l--}
       {printf "%c", $0}'

사용하십시오 sed(내부에 개행 문자가 없다고 가정 [...]):

sed -e 's/_/_u/g;:1' -e 's/\(\[[^][]*\)\[\([^][]*\)]/\1_o\2_c/g;t1' \
    -e :2 -e 's/\(\[[^]]*\)[[:space:]]/\1/g;t2' \
    -e 's/_c/]/g;s/_o/[/g;s/_u/_/g'

고려되다공백ASCII 문자 집합의 가로(SPC, TAB) 또는 세로(NL, CR, VT, FF...) 간격 문자 위에 있습니다. 로케일에 따라 다른 항목이 포함될 수도 있습니다.

답변2

Perl 5.14 솔루션(더 짧고 읽기 쉽다고 생각합니다. 특히 파일에서 한 줄이 아닌 여러 줄로 형식을 지정하는 경우)

perl -pE 's{(\[ .*? \])}{$1 =~ y/ //dr}gex'

5.14에서는 정규식 엔진이 재진입 가능하기 때문에 이것이 가능합니다. 여기에서 확장하고 의견을 제시하세요.

s{
    (\[ .*? \])         # search for [ ... ] block, capture (as $1)
}{
    $1 =~ y/ //dr       # delete spaces. you could add in other whitespace here, too
                        # d = delete; r = return result instead of modifying $1
}gex; # g = global (all [ ... ] blocks), e = replacement is perl code, x = allow extended regex

답변3

펄 솔루션:

perl -pe 's/(\[[^]]*?)\s([^][]*\])/$1$2/ while /\[[^]]*?\s[^][]*\]/'

관련 정보