'tr'만 사용하여 여러 공백을 하나로 대체하십시오.


71

파일이 있습니다 f1.txt:

ID     Name
1      a
2         b
3   g
6            f

공백 수는 고정되어 있지 않습니다 . 모든 공백을 하나의 공백으로 만 바꾸는 가장 좋은 방법은 무엇입니까 tr?

이것이 지금까지 내가 가진 것입니다.

cat f1.txt | tr -d " "

그러나 결과는 다음과 같습니다.

IDName
1a
2b
3g
6f

그러나 나는 다음과 같이 보이기를 원합니다.

ID Name
1 a
2 b
3 g
6 f

시도하고 피하십시오 sed.


6
sed를 피하는 것이 왜 그렇게 중요한가? 어떤 것이 든 사용하십시오!
David Richerby

7
나는 그것을하는 방법을 알고 있기 때문에 sed. 다른 방법을 알고 싶었다
:)

답변:


106

tr사용하면 squeeze repeat 옵션을 사용하십시오 .

$ tr -s " " < file
ID Name
1 a
2 b
3 g
6 f

또는 awk솔루션을 사용할 수 있습니다 .

$ awk '{$2=$2};1' file
ID Name
1 a
2 b
3 g
6 f

레코드에서 필드를 변경하면 awkrebuild $0는 모든 필드를 가져 와서 함께 연결합니다 ( OFS기본적으로 공백 임).

일련의 공백과 탭 (및 로케일 및 구현에 따라 다른 공백 문자 awk)을 한 공백으로 압축 하고 각 행에서 앞뒤 공백을 제거합니다.


1
이것도 훌륭한 솔루션입니다. . . 나는 어느 것을 선택해야할지 모르겠다 : / @Gnouc
gkmohit

원하는 솔루션을 자유롭게 선택하면 효과가 있습니다. 내 솔루션은 @polym의 답변과 다릅니다.
cuonglm

1
:)) 예! @Gnouc의 대답은 그가 동적이기 때문에 실제로 사용합니다 awk. 그의 해결책을 받아 들일 수도 있습니다. 한가지 : Gnouc 명령에서 awk 형식이 무엇을 설명 할 수 있습니까? 또한 출력이 알 수없는 예상 출력을 준수하도록 탭 / 공백을 추가 할 수 있습니까?
polym

1
@ polym : Unknown의 마지막 편집으로 그는 하나의 공백 만 원하고 출력은 column -t하지 않는 것 같습니다 . 에 대한 설명을 추가하십시오 awk.
cuonglm

4
여기에는 약간의 차이가 있습니다. tr줄 끝의 두 공백을 단일 공백으로 바꿉니다. awk후행 공백을 모두 제거합니다.
앤 반 로섬

19

그냥 사용하십시오 column:

column -t inputFile

산출:

ID  Name
1   a
2   b
3   g
6   f

멋진과 빠른 응답 :
gkmohit

1
@ 알 수없는 훌륭한 서비스 :)!
polym

1
@Gnouc wow cool, column도 파일을 인수로 사용합니다. 좋은 감사합니다!
polym

원하는 경우에만 두 번째 열을 어떻게 얻을 수 있습니까? 나는 시도했지만 column -t f1.txt | cut -d " " -f2 해결책은 아니었다
gkmohit

2
그런 다음 awk를 사용하십시오 : column -t file | awk '{print $2}'두 번째 열만 인쇄합니다
polym

8

"공백"을 쥐고 싶다면 tr의 사전 정의 된 문자 세트 ": blank :"(가로 공백 탭 및 공백) 또는 ": space :"(수직 공백)를 사용하려고합니다.

/bin/echo -e  "val1\t\tval2   val3" | tr -s "[:blank:]"

Red Hat 5 (GNU tr)에서 예제를 실행했습니다.

필자의 경우 모든 공백을 단일 공간으로 정규화하여 공간을 델리 미터로 사용할 수있었습니다.

dastrobu의 두 번째 의견에서 지적했듯이 맨 페이지의 문구를 놓쳤습니다.

 -s uses the last specified SET, and occurs after translation or deletion.

이를 통해 첫 번째 tr을 제거 할 수 있습니다. Kudo는 나의 조밀함에 직면 한 그의 인내심을 위해 스콧해야합니다.

이전에 Redis 구성에서 포트를 구문 분석하십시오. 파일:

grep "^port" $redisconf | tr "[:blank:]" " " | tr -s "[:blank:]"  | cut -d" " -f2

그런 다음 SET2를 압착으로 지정하십시오.

grep "^port" $redisconf | tr -s "[:blank:]" " " | cut -d" " -f2

산출:

6379

공백의 뉘앙스를 다루는 자세한 내용

[: blank :] 문자 클래스에 속하는 연속 혼합 문자가 포함 된 경우 스퀴즈 만 실패하는 위치를 보여줍니다.

 /usr/bin/printf '%s \t %s' id myname | tr -s "[:blank:]"  | od -cb
0000000   i   d      \t       m   y   n   a   m   e
        151 144 040 011 040 155 171 156 141 155 145
0000013

참고 : printf 형식의 두 문자열 필드는 1 개의 공백, 1 개의 탭, 1 개의 공백으로 구분됩니다. 짜낸 후에도이 순서는 여전히 존재합니다. 8 진 덤프의 출력에서 ​​이는 ASCII 시퀀스 040 011 040으로 표시됩니다.


1
정말로 필요 tr "[:blank:]" " " | tr -s "[:blank:]"합니까? 첫 번째 부분으로 충분 tr "[:blank:]" " "하다고 생각합니다. 즉, 공백을 정규화하고 이미 대체를 수행하기 때문입니다. 매뉴얼 페이지에서 : "문자의 여러 항목을 꽉 쥐십시오 ...] 이것은 모든 삭제와 번역이 완료된 후에 발생합니다."
dastrobu

2
´tr -s "[: blank :]" ""´ 먼저 모든 공백을 공백으로 변환 한 다음 공백을 압착해야합니다. 두 번째 'tr'필요가 없습니다.
dastrobu

1
printf 'ID \t Name\n' | tr -s "[:blank:]" " " | od -cb(@dastrobu에서 제안한대로) 시도 하고 출력으로 ID Name\n( 공간) 있습니다. 실제로 시도 했습니까, @ user3183018?
Scott

1
좋아, 다시 말해 보자. 나는 공간을 나타내는 ( printf 'ID␣\t␣Name\n' | tr -s "[:blank:]" "␣"  @dastrobu가 제안한 대로)하고 출력을 (한 공간으로) 얻었습니다 ID␣Name\n. 이것은 질문의 제목 문자열을 사용한 것을 제외하고는 "Port <SPACE> <TAB> <SPACE> 6379" 의 예 와 정확히 동일 합니다 . 나는 당신이 tr -s "[:blank:]"(최종 "␣"논쟁 없이) 시도했는지 궁금합니다  .
Scott

1
내가 할 때 printf 'ID \t Name\n' | od -cb, 정확히 무엇을 해야하는지 보여줍니다 : ID ⁠  \t ⁠  N a m e \n(즉,  ID 040 011 040 N a m e\n). 한편, 당신 자신의 증거에 의해, 당신은 내가 당신이라고 생각했던 오류를 정확하게 만들고 있습니다 : @dastrobu와 나는 지금 네 번 제시 한 명령 대신에 당신이 달리고 있습니다 tr -s "[:blank:]"(즉,  tr하나의 옵션과  하나의 인수로). tr -s '[:blank:]' '␣'(즉,  tr하나의 옵션과  두 개의 인수로 ).
Scott

5

셸 이외의 프로그램이 필요한 사람은 누구입니까?

while read a b
do
    echo "$a $b"
done < f1.txt

polym의 column답변 에서와 같이 두 번째 열의 값을 정렬 하려면 다음 printf대신 사용하십시오 echo.

while read a b
do
    printf '%-2s %s\n' "$a" "$b"
done < f1.txt

1
첫 번째로 tr과 비교할 때 입력이 너무 작 으면 tr호출 비용이 너무 적지 않는 한 효율성 측면에서 끔찍한 제안 입니다. 마지막으로,이 게시물이 실제로 질문에 대한 답변을하지는 않는다고 말하지 않습니까? tr 만 사용하여 모든 공백을 하나의 공백으로 바꾸는 가장 좋은 방법은 무엇입니까?
mikeserv

1
게다가-더 쉽게 무언가를 할 수 없었 $IFS습니까? 어쩌면 : IFS=' <tab>' set -f ; echo $(cat <file)?
mikeserv

2

이것은 오래된 질문이며 여러 번 해결되었습니다. 완전성을 위해 : 나는 비슷한 문제가 있었지만 파이프를 통해 다른 프로그램으로 라인을 전달하고 싶었습니다. 나는 xargs을 사용했다 .

-L max-lines
   Use at most max-lines nonblank input lines per command line.
   Trailing blanks cause an input line to be logically continued 
   on the next input line.  Implies -x.

그래서 cat f1.txt | xargs -L1정확하게 당신이 원하는 출력으로 보인다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.