일부 출력의 각 줄에서 선행 및 후행 공백을 자르려면 어떻게합니까?


154

출력의 각 줄에서 모든 선행 및 후행 공백과 탭을 제거하고 싶습니다.

trim출력을 파이프로 연결할 수 있는 간단한 도구 가 있습니까?

예제 파일 :

test space at back 
 test space at front
TAB at end  
    TAB at front
sequence of some    space in the middle
some empty lines with differing TABS and spaces:





 test space at both ends 

1
줄 바꿈을 제거하는 솔루션을 찾고있는 사람에게는 다른 문제입니다. 정의에 의해 개행은 새로운 행의 텍스트를 작성합니다. 따라서 한 줄의 텍스트는 개행을 포함 할 수 없습니다. 묻고 싶은 질문은 문자열의 시작 또는 끝에서 줄 바꿈을 제거하는 방법 ( stackoverflow.com/questions/369758 ) 또는 공백 인 빈 줄 또는 공백을 제거하는 방법입니다. serverfault.com/questions/252921
Tony

답변:


198
awk '{$1=$1;print}'

또는 더 짧은 :

awk '{$1=$1};1'

선행 및 후행 공백이나 탭 문자 트림겠습니까 1 하나의 공간으로 탭과 공간의 시퀀스를 짠다.

당신이 중 하나에 뭔가를 할당 할 때 때문 작동 필드 , awk(인쇄로 전체 기록을 재 구축 print) (모든 필드에 가입하여 $1, ..., $NF로) OFS(기본적으로 공간).

1 (및 로캘 및 awk구현 에 따라 다른 빈 문자 )


2
두 번째 예의 세미콜론은 불필요한 것입니다. 사용 가능 :awk '{$1=$1}1'
Brian


재미있는 ... gawk, mawk 및 OS X의 awk는 세미콜론을 지원하지 않습니다. (적어도 내 버전 (각각 1.2, 4.1.1 및 20070501)의 경우)
Brian

1
이 접근법에 대해 내가 싫어하는 유일한 것은 라인 내에서 반복되는 공백을 잃는 것입니다. 예를 들면 다음과 같습니다.echo -e 'foo \t bar' | awk '{$1=$1};1'
user.friendly

2
echo ' hello ' | xargs
JREAM

44

GNU를 사용하는 경우 명령을 압축 할 수 있습니다 sed.

$ sed 's/^[ \t]*//;s/[ \t]*$//' < file

위의 명령이 작동합니다.

$ echo -e " \t   blahblah  \t  " | sed 's/^[ \t]*//;s/[ \t]*$//'
blahblah

명령이 원하는 문자를 올바르게 제거 hexdump하는지 확인하는 데 사용할 수 있습니다 sed.

$ echo -e " \t   blahblah  \t  " | sed 's/^[ \t]*//;s/[ \t]*$//' | hexdump -C
00000000  62 6c 61 68 62 6c 61 68  0a                       |blahblah.|
00000009

캐릭터 클래스

문자 그대로 다음과 같은 세트를 나열하는 대신 문자 클래스 이름을 사용할 수도 있습니다 [ \t].

$ sed 's/^[[:blank:]]*//;s/[[:blank:]]*$//' < file

$ echo -e " \t   blahblah  \t  " | sed 's/^[[:blank:]]*//;s/[[:blank:]]*$//'

정규식 (regex)을 사용하는 대부분의 GNU 도구는 이러한 클래스를 지원합니다.

 [[:alnum:]]  - [A-Za-z0-9]     Alphanumeric characters
 [[:alpha:]]  - [A-Za-z]        Alphabetic characters
 [[:blank:]]  - [ \x09]         Space or tab characters only
 [[:cntrl:]]  - [\x00-\x19\x7F] Control characters
 [[:digit:]]  - [0-9]           Numeric characters
 [[:graph:]]  - [!-~]           Printable and visible characters
 [[:lower:]]  - [a-z]           Lower-case alphabetic characters
 [[:print:]]  - [ -~]           Printable (non-Control) characters
 [[:punct:]]  - [!-/:-@[-`{-~]  Punctuation characters
 [[:space:]]  - [ \t\v\f]       All whitespace chars
 [[:upper:]]  - [A-Z]           Upper-case alphabetic characters
 [[:xdigit:]] - [0-9a-fA-F]     Hexadecimal digit characters

리터럴 세트 대신 이것들을 사용하는 것은 항상 공간 낭비처럼 보이지만, 코드가 이식 가능하거나 대체 문자 세트를 다루어야하는 경우 (국제 생각), 클래스 이름을 사용하고 싶을 것입니다 대신에.

참고 문헌


즉 주 [[:space:]]와 일치하지 않는 [ \t]일반적인 경우 (유니 등)이다. [[:space:]]아마 (공백의 더 많은 종류의 단지보다 유니 코드에 있기 때문에 훨씬 느립니다 ' ''\t'). 다른 사람들도 마찬가지입니다.
Olivier Dulac

sed 's/^[ \t]*//'휴대용이 아닙니다. POSIX는 일련의 공백, 백 슬래시 또는 t문자 를 제거해야하기 때문에 GNU sedPOSIXLY_CORRECT환경에 있을 때도 그렇게 합니다.
Stéphane Chazelas

개행 문자를 자르려면 어떻게해야합니까? '\ n \ 없음 텍스트 \ n \ n'
유진 Biryukov

나는 awk 솔루션과 같은 다른 부작용이 없기 때문에 sed 솔루션을 좋아합니다. OSX jsut에서 bash에서 시도했을 때 첫 번째 변형이 작동하지 않지만 문자 클래스 버전은 작동합니다.sed 's/^[[:blank:]]*//;s/[[:blank:]]*$//'
Tony

@EugeneBiryukov는 원래 게시물에 대한 내 의견을 참조하십시오
Tony

23

허용 된 답변에서 Stéphane Chazelas 가 제안한대로 이제
스크립트를 작성할 수 있습니다 /usr/local/bin/trim.

#!/bin/bash
awk '{$1=$1};1'

해당 파일 실행 권한을 부여하십시오.

chmod +x /usr/local/bin/trim

이제 모든 출력을 trim예를 들어 다음과 같이 전달할 수 있습니다 .

cat file | trim

(아래 의견 : 나는 이것을 전에 사용했다 : while read i; do echo "$i"; done
그것은 잘 작동하지만 성능이 떨어짐)


1
파일이 크거나 백 슬래시가 포함 된 경우 행운을 빕니다.
don_crissti

1
@ don_crissti : 조금 더 주석을 달 수 있습니까?, 어떤 파일이 큰 파일에 더 적합합니까? 파일에 백 슬래시가 포함되어 있으면 솔루션을 어떻게 수정할 수 있습니까?
rubo77

3
while read -r line백 슬래시를 유지하고 심지어는 계속 사용해야 합니다 . 거대한 파일 / 속도와 관련하여 실제로 최악의 솔루션을 선택했습니다. 나는 거기에 더 나쁜 것이 없다고 생각합니다. 왜 쉘 루프를 사용하여 텍스트를 잘못 연습합니까?에 대한 답변을 참조하십시오 . 속도 벤치 마크에 대한 링크를 추가 한 마지막 답변에 대한 의견을 포함합니다. sed여기에 대답은 IMO 완벽하게 벌금보다 훨씬 더 낫다 read.
don_crissti

@don_crissti ... 및 / 또는 -1 개 이상의 e, E 또는 n 문자의 조합으로 시작 하고 그 뒤에 NUL 문자를 포함하는 행이 있습니다. 또한 마지막 개행 후 종료되지 않은 행은 건너 뜁니다.
Stéphane Chazelas

1
/ etc / profile (또는 ~ / .bashrc 또는 ~ / .zshrc 등)에 별칭을 추가 할 수도 있습니다. alias trim = "awk '{\ $ 1 = \ $ 1}; 1'"
Jeff Clayton

22

인수없이 xargs가 그렇게합니다.

예:

trimmed_string=$(echo "no_trimmed_string" | xargs) 

1
이것은 또한 질문에서 요청하지 않은 선에서 여러 공간을 계약
roaima

1
@roaima-true이지만 허용되는 답변도 공백을 묻습니다 (질문에서 요청하지 않음). 여기에 실제 문제 xargs는 입력에 백 슬래시와 작은 따옴표가 포함되어 있으면 전달하지 못하는 것입니다.
don_crissti

@don_crissti는 허용 된 답변이 질문에 따라 올바르게 대답한다는 것을 의미하지는 않습니다. 그러나이 경우 여기에서 경고로 표시되지 않았지만 허용 된 대답에서는 그렇지 않았습니다. 장래 독자와 관련이있는 경우를 대비하여 사실을 강조했습니다.
roaima

작은 따옴표, 큰 따옴표, 백 슬래시 문자도 구분합니다. 또한 하나 이상의 echo호출을 실행합니다. 일부 반향 구현은 옵션 및 / 또는 백 슬래시도 처리합니다. 단일 행 입력에만 적용됩니다.
Stéphane Chazelas

17
sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//'

쉘 변수에 줄을 읽고 있다면 달리 지시하지 않는 한read 이미 수행합니다 .


1
일에 대한 read. 따라서 읽는 동안 파이프하면 작동합니다.cat file | while read i; do echo $i; done
rubo77

1
예제에서 인용되지 않은 변수도 쉘에서 다시 처리한다는 점을 제외하고 @rubo. echo "$i"read
roaima

13

행을 변수로 저장하면 bash를 사용하여 작업을 수행 할 수 있습니다.

문자열에서 선행 공백을 제거하십시오.

shopt -s extglob
echo ${text##+([[:space:]])}

문자열에서 후행 공백을 제거하십시오.

shopt -s extglob
echo ${text%%+([[:space:]])}

문자열에서 모든 공백을 제거하십시오.

echo ${text//[[:space:]]}

문자열에서 모든 공백을 제거하는 것은 선행 및 후행 공백을 모두 제거하는 것과 다릅니다 (문제).
catpnosis 2016 년

가장 좋은 해결책은 bash 내장 만 필요하고 외부 프로세스 포크가 필요하지 않습니다.
peterh

2
좋은. 스크립트가 외부 프로그램 (예 : awk 또는 sed)을 가져올 필요가없는 경우 스크립트가 훨씬 빠르게 실행됩니다. 이것은 ksh의 "modern"(93u +) 버전에서도 작동합니다.
user1683793

9

'piped'도구 덕분에 주어진 행에서 모든 선행 및 후행 공백을 제거하기 위해 완전히 다른 3 가지 방법을 식별 할 수 있습니다. 이러한 차이점은 입력 줄의 단어 사이의 공백과 관련이 있습니다. 예상되는 동작에 따라 선택해야합니다.

차이점을 설명하려면 다음 더미 입력 라인을 고려하십시오.

"   \t  A   \tB\tC   \t  "

tr

$ echo -e "   \t  A   \tB\tC   \t  " | tr -d "[:blank:]"
ABC

tr정말 간단한 명령입니다. 이 경우 공백 또는 표 문자를 삭제합니다.

어 wk

$ echo -e "   \t  A   \tB\tC   \t  " | awk '{$1=$1};1'
A B C

awk 선행 및 후미 공백을 삭제하고 단어 사이의 모든 공백을 단일 공백으로 압축합니다.

sed

$ echo -e "   \t  A   \tB\tC   \t  " | sed 's/^[ \t]*//;s/[ \t]*$//'
A       B   C

이 경우 sed단어 사이의 공백을 건드리지 않고 선행 및 후행 공백을 삭제합니다.

말:

한 줄에 하나의 단어가 있으면 tr작업을 수행합니다.


이 중 어느 것도 생각 / 선도 줄 바꿈 후행하지 트림
highmaintenance

(때로는 예기치 않은) 출력을 가진 솔루션 목록은 +1입니다.
Tony

@ user61382 이것은 다소 늦었지만 원래 게시물에 대한 내 의견을 참조하십시오.
Tony

@highmaintenance : 줄 바꿈도 제거하려면 :과 같은 [:space:]명령에 [: blank :] 대신을 사용 하십시오. (참조 : )tr... | tr -d [:space:]man tr
tron5

6

sed는이를위한 훌륭한 도구입니다.

                        # substitute ("s/")
sed 's/^[[:blank:]]*//; # parts of lines that start ("^")  with a space/tab 
     s/[[:blank:]]*$//' # or end ("$") with a space/tab
                        # with nothing (/)

당신은 당신의 경우를 위해 텍스트에 배관 중 하나를 사용할 수 있습니다

<file sed -e 's/^[[...

또는 sedGNU 인 경우 '인라인'으로 행동하십시오 .

sed -i 's/...' file

그러나 소스를 이런 식으로 변경하면 제대로 작동하지 않을 때 (또는 작동 할 때조차도) 복구 할 수 없으므로 "위험한"것이므로 먼저 백업 (또는 -i.bak일부 BSD에 이식 할 수있는 이점이있는 사용 sed) !


2

번역 명령이 작동합니다

cat file | tr -d [:blank:]

4
이 명령은 앞 / 뒤 공백뿐만 아니라 파일에서 모든 공백을 제거하므로 올바르지 않습니다.
Brian Redbeard

@BrianRedbeard 당신이 맞습니다. 이것은 공백없이 모 놀리 식 문자열에 여전히 유용한 답변입니다.
Anthony Rutledge

0

자르려고하는 문자열이 짧고 연속적이거나 연속적이라면 간단히 bash 함수에 매개 변수로 전달할 수 있습니다.

    trim(){
        echo $@
    }

    a="     some random string   "

    echo ">>`trim $a`<<"
Output
>>some random string<<
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.