Thay thế nhiều khoảng trắng bằng một chỉ sử dụng 'tr'


71

Tôi có một tập tin , f1.txt:

ID     Name
1      a
2         b
3   g
6            f

Số lượng không gian không cố định. Cách tốt nhất để thay thế tất cả các khoảng trắng bằng một không gian chỉ sử dụng là trgì?

Đây là những gì tôi có cho đến nay:

cat f1.txt | tr -d " "

Nhưng đầu ra là:

IDName
1a
2b
3g
6f

Nhưng tôi muốn nó trông như thế này:

ID Name
1 a
2 b
3 g
6 f

Hãy cố gắng và tránh sed.


6
Tại sao nó rất quan trọng để tránh sed? Sử dụng bất cứ công việc gì!
David Richerby

7
Bởi vì tôi biết làm thế nào để làm điều đó với sed. Muốn biết những cách khác :)
gkmohit

Câu trả lời:


106

Với tr, sử dụng tùy chọn lặp lại squeeze :

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

Hoặc bạn có thể sử dụng một awkgiải pháp:

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

Khi bạn thay đổi một trường trong bản ghi, awkxây dựng lại $0, lấy tất cả các trường và ghép chúng lại với nhau, cách nhau bởi OFSđó là một khoảng trắng theo mặc định.

Điều đó sẽ nén các chuỗi không gian và các tab (và có thể các ký tự trống khác tùy thuộc vào miền địa phương và việc thực hiện awk) vào một khoảng trắng, nhưng cũng loại bỏ các khoảng trống hàng đầu và dấu ở cuối mỗi dòng.


1
Đây là một giải pháp tuyệt vời quá. . . Tôi không biết nên chọn cái nào bây giờ: / @Gnouc
gkmohit

Hãy thoải mái chọn bất kỳ giải pháp nào bạn thích và nó phù hợp với bạn. Một lưu ý rằng giải pháp của tôi khác với câu trả lời của @ polym.
cuonglm

1
:)) yay! Câu trả lời của @Gnouc thực sự năng động, bởi vì anh ấy sử dụng awk, anh ấy có thể làm bất cứ điều gì. Bạn cũng có thể chấp nhận giải pháp của mình. Chỉ có một điều: Gnouc bạn có thể giải thích định dạng awk trong lệnh của bạn không? Ngoài ra, bạn có thể thêm các tab / khoảng trắng để đầu ra phù hợp với đầu ra dự kiến ​​của Unknown không?
polym

1
@polym: Với lần chỉnh sửa cuối cùng của Unknown, anh ta dường như chỉ muốn một khoảng trắng, không xuất ra như thế column -t. Thêm giải thích cho awk.
cuonglm

4
Có một sự khác biệt nhỏ ở đây. trsẽ thay thế hai khoảng trắng ở cuối dòng bằng một khoảng trắng. awksẽ loại bỏ tất cả các dấu cách.
Anne van Rossum

19

Chỉ cần sử dụng column:

column -t inputFile

Đầu ra:

ID  Name
1   a
2   b
3   g
6   f

Tuyệt vời và trả lời nhanh :)
gkmohit

1
@Un Unknown Tuyệt vời để được phục vụ :)!
polym

1
@Gnouc wow tuyệt vời, cột cũng lấy một tệp làm đối số. cảm ơn rất nhiều
polym

Làm thế nào tôi có thể nhận được cột thứ hai chỉ khi tôi muốn? Tôi đã thử column -t f1.txt | cut -d " " -f2 Nhưng không phải là một giải pháp tôi mong đợi
gkmohit

2
Sử dụng awk sau đó: chỉ column -t file | awk '{print $2}'in cột thứ hai
polym

8

Nếu bạn muốn ép "khoảng trắng", bạn sẽ muốn sử dụng các bộ ký tự được xác định trước của tr ": blank:" (tab khoảng trắng ngang và khoảng trắng) hoặc ": space:" (khoảng trắng chính xác):

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

Ví dụ đã được chạy trên Red Hat 5 (GNU tr).

Trong trường hợp của tôi, tôi muốn bình thường hóa tất cả các khoảng trắng thành một không gian duy nhất để tôi có thể dựa vào không gian như là một trình phân phối.

Như được chỉ ra bởi bình luận thứ hai của dastrobu, tôi đã bỏ lỡ từ ngữ trong trang người đàn ông:

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

Điều này cho phép chúng tôi loại bỏ tr đầu tiên. Kudo phải đi tìm sự kiên nhẫn của anh ấy trước sự dày đặc của tôi.

Trước đó, phân tích cổng từ cấu hình Redis. tập tin:

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

Sau đó, với SET2 được chỉ định với bóp:

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

Đầu ra:

6379

Để biết thêm chi tiết bao gồm các sắc thái của khoảng trắng

Chứng minh rằng việc ép một mình thất bại khi các ký tự hỗn hợp liên tiếp rơi vào lớp nhân vật [: blank:] có liên quan:

 /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

Lưu ý: Hai trường chuỗi của tôi ở định dạng printf được phân tách bằng 1 khoảng trắng, 1 tab, 1 khoảng trắng. Sau khi vắt thì trình tự này vẫn tồn tại. Trong đầu ra của bãi chứa Octal, điều này được thể hiện bằng chuỗi ascii 040 011 040.


1
Bạn có thực sự cần tr "[:blank:]" " " | tr -s "[:blank:]"? Tôi đoán phần đầu tiên sẽ đủ, tức là tr "[:blank:]" " "vì nó bình thường hóa khoảng trắng và đã thay thế. Từ trang man: "Bóp nhiều lần xuất hiện của các ký tự [...] Điều này xảy ra sau khi hoàn thành việc xóa và dịch."
dastrobu

2
vì vậy, ´tr Không cần một giây thứ hai.
dastrobu

1
Tôi đã thử printf 'ID \t Name\n' | tr -s "[:blank:]" " " | od -cb(theo đề xuất của @dastrobu) và tôi nhận được ID Name\n(với một khoảng trắng ) làm đầu ra. Bạn đã thực sự thử nó chưa, @ user3183018?
Scott

1
OK, hãy để tôi thử nói điều này một lần nữa. Tôi đã làm printf 'ID␣\t␣Name\n' | tr -s "[:blank:]" "␣"  (như được đề xuất bởi @dastrobu), nơi đại diện cho một không gian và tôi đã nhận ID␣Name\n(với một khoảng trắng ) làm đầu ra. Điều này giống hệt như ví dụ của bạn về Cổng Cổng <SPACE> <TAB> <SPACE> 6379, ngoại trừ tôi đã sử dụng các chuỗi tiêu đề từ câu hỏi. Tôi đang tự hỏi liệu bạn đã thử  tr -s "[:blank:]"(không có "␣"đối số cuối cùng ).
Scott

1
Khi tôi làm printf 'ID \t Name\n' | od -cb, nó hiển thị chính xác những gì nó được cho là: ID ⁠  \t ⁠  N a m e \n(tức là  ID 040 011 040 N a m e\n). Trong khi đó, bằng chứng của riêng bạn, bạn đang mắc chính xác lỗi mà tôi đoán rằng bạn là: bạn đang chạy tr -s "[:blank:]"(nghĩa là  trvới một tùy chọn và  một đối số), thay vì lệnh mà @dastrobu và tôi đã trình bày bốn lần bây giờ: tr -s '[:blank:]' '␣'(nghĩa là  trvới một tùy chọn và  hai đối số ).
Scott

5

Ai cần một chương trình (trừ vỏ)?

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

Nếu bạn muốn các giá trị trong cột thứ hai xếp hàng, như trong columncâu trả lời của polym , hãy sử dụng printfthay vì echo:

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

1
Ở nơi đầu tiên, khi so sánh với tr - đây là một gợi ý cực kỳ hiệu quả, khôn ngoan trừ khi đầu vào quá nhỏ vượt quá chi phí nhỏ của trlời mời - không đề cập đến việc phải viết thêm bao nhiêu công sức. Cuối cùng, bạn sẽ không nói rằng bài đăng này không thực sự trả lời câu hỏi như đã hỏi? Cách tốt nhất để thay thế tất cả các khoảng trắng bằng một không gian chỉ sử dụng tr là gì?
mikeerv

1
Và bên cạnh đó - bạn không thể dễ dàng làm điều gì đó hơn $IFSsao? Có lẽ như : IFS=' <tab>' set -f ; echo $(cat <file)?
mikeerv

2

Đây là một câu hỏi cũ và được giải quyết nhiều lần. Chỉ để cho đầy đủ: Tôi đã có một vấn đề về simillar, nhưng muốn chuyển các dòng thông qua đường ống đến chương trình chống nhiệt. Tôi đã sử dụng 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.

vì vậy cat f1.txt | xargs -L1dường như để xuất ra chính xác những gì bạn muốn.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.