In tất cả trừ ba cột đầu tiên


112

Quá cồng kềnh:

awk '{print " "$4" "$5" "$6" "$7" "$8" "$9" "$10" "$11" "$12" "$13}' things

43
Có lý do gì bạn không thể sử dụng cut -f3-?
Cascabel

1
@hhh hay quá .. Tôi thích ý tưởng về câu trả lời tóm tắt.
Chris Seymour

2
@Jefromi - bởi vì có những vấn đề đệm phù hợp với cắt, mà awk không có: stackoverflow.com/questions/14360640/...
sdaau


@Jefromi - cũng cutkhông có regexes trước {}các hành động, và sau đó nó là cách với các dấu phân cách trường (số lượng khoảng trắng thay đổi?), Và bạn phải chỉ định chúng theo cách thủ công. Tôi nghĩ OP muốn nghe về một số shift Nlệnh không tồn tại. Gần nhất là $1="";$2="";(...);print}, nhưng trong trường hợp của tôi, nó để lại một số khoảng trắng ở đầu (có thể là dấu phân cách).
Tomasz Gandor

Câu trả lời:


50

Một giải pháp không thêm khoảng trắng ở đầu hoặc cuối :

awk '{ for(i=4; i<NF; i++) printf "%s",$i OFS; if(NF) printf "%s",$NF; printf ORS}'

### Example ###
$ echo '1 2 3 4 5 6 7' |
  awk '{for(i=4;i<NF;i++)printf"%s",$i OFS;if(NF)printf"%s",$NF;printf ORS}' |
  tr ' ' '-'
4-5-6-7

Sudo_O đề xuất một cải tiến thanh lịch bằng cách sử dụng toán tử bậc baNF?ORS:OFS

$ echo '1 2 3 4 5 6 7' |
  awk '{ for(i=4; i<=NF; i++) printf "%s",$i (i==NF?ORS:OFS) }' |
  tr ' ' '-'
4-5-6-7

EdMorton cung cấp một giải pháp duy trì các khoảng trắng ban đầu giữa các trường:

$ echo '1   2 3 4   5    6 7' |
  awk '{ sub(/([^ ]+ +){3}/,"") }1' |
  tr ' ' '-'
4---5----6-7

BinaryZebra cũng cung cấp hai giải pháp tuyệt vời:
(các giải pháp này thậm chí còn bảo toàn các khoảng trống ở cuối từ chuỗi gốc)

$ echo -e ' 1   2\t \t3     4   5   6 7 \t 8\t ' |
  awk -v n=3 '{ for ( i=1; i<=n; i++) { sub("^["FS"]*[^"FS"]+["FS"]+","",$0);} } 1 ' |
  sed 's/ /./g;s/\t/->/g;s/^/"/;s/$/"/'
"4...5...6.7.->.8->."

$ echo -e ' 1   2\t \t3     4   5   6 7 \t 8\t ' |
  awk -v n=3 '{ print gensub("["FS"]*([^"FS"]+["FS"]+){"n"}","",1); }' |
  sed 's/ /./g;s/\t/->/g;s/^/"/;s/$/"/'
"4...5...6.7.->.8->."

Giải pháp được đưa ra bởi larsr trong các bình luận gần như đúng:

$ echo '1 2 3 4 5 6 7' | 
  awk '{for (i=3;i<=NF;i++) $(i-2)=$i; NF=NF-2; print $0}' | tr  ' ' '-'
3-4-5-6-7

Đây là phiên bản cố định và được tham số hóa của giải pháp larsr :

$ echo '1 2 3 4 5 6 7' | 
  awk '{for(i=n;i<=NF;i++)$(i-(n-1))=$i;NF=NF-(n-1);print $0}' n=4 | tr ' ' '-'
4-5-6-7

Tất cả các câu trả lời khác trước tháng 9 năm 2013 đều tốt nhưng thêm khoảng trắng:


Câu trả lời của EdMorton không phù hợp với tôi (bash 4.1.2 (1) -release, GNU Awk 3.1.7 hoặc bash 3.2.25 (1) -release, GNU Awk 3.1.5) nhưng được tìm thấy ở đây theo cách khác:echo ' This is a test' | awk '{print substr($0, index($0,$3))}'
elysch

1
@elysch không, điều đó sẽ không hoạt động nói chung, nó chỉ hoạt động với một số giá trị đầu vào cụ thể. Xem bình luận tôi đã thêm bên dưới bình luận của bạn dưới câu trả lời của tôi.
Ed Morton

1
Xin chào @fedorqui. Câu trả lời của tôi là câu đầu tiên. Trong câu trả lời ban đầu của tôi, tôi đã giải thích tại sao câu trả lời khác không đúng (thêm khoảng trắng ở đầu hoặc cuối). Một số người đã đề xuất các cải tiến trong nhận xét. Chúng tôi đã yêu cầu OP chọn một câu trả lời đúng hơn và anh ấy / cô ấy đã chọn câu trả lời của tôi. Sau khi một số cộng tác viên khác đã chỉnh sửa câu trả lời của tôi để tham khảo câu trả lời đó (xem lịch sử). Bạn đã rõ chưa? Bạn khuyên tôi điều gì để cải thiện khả năng hiểu câu trả lời của tôi? Chúc mừng ;-)
olibre

1
Bạn hoàn toàn đúng và tôi rất xin lỗi vì sự hiểu lầm của mình. Tôi đã đọc nhanh câu trả lời và không nhận thấy câu trả lời ban đầu của bạn (vâng, tôi đọc quá nhanh). +1 cho chính câu trả lời bằng cách sử dụng thủ thuật hay để lặp lại đến NF-1 và sau đó in phần tử cuối cùng để tránh khoảng trắng thừa. Và xin lỗi một lần nữa! (sẽ xóa bình luận của tôi trong một ngày hoặc lâu hơn, để tránh những hiểu lầm từ độc giả trong tương lai).
fedorqui 'SO dừng hại'

1
Tôi sẽ sử dụng một số loại tiêu đề: <câu trả lời của bạn> và sau đó là quy tắc hàng ngang theo sau là tiêu đề lớn "so sánh các câu trả lời khác". Nếu không, di chuyển so sánh này để câu trả lời khác, vì rõ ràng là người có xu hướng thích câu trả lời ngắn trong một "gimme mã của tôi" Tầm nhìn:)
fedorqui 'SO dừng hại'

75
awk '{for(i=1;i<4;i++) $i="";print}' file

4
Điều này sẽ để lại hàng đầu OFSvì bạn không đối phó với NFkhoảng trống hàng đầu trong bản ghi.
Chris Seymour

70

sử dụng cắt

$ cut -f4-13 file

hoặc nếu bạn nhấn mạnh vào awk và $ 13 là trường cuối cùng

$ awk '{$1=$2=$3="";print}' file

khác

$ awk '{for(i=4;i<=13;i++)printf "%s ",$i;printf "\n"}' file

14
có lẽ tốt hơn nên sử dụng "NF" hơn "13" trong ví dụ cuối cùng.
glenn jackman

2
2 kịch bản do OP quyết định. nếu 13 là trường cuối cùng, sử dụng NF là được. Nếu không, sử dụng 13 là thích hợp.
ghostdog 74

3
Thứ 2 cần xóa 3 bản sao của OFS từ đầu $ 0. Thứ 3 sẽ tốt hơn với printf "%s ",$i, vì bạn không biết liệu $icó thể chứa %shoặc tương tự. Nhưng điều đó sẽ in thêm một khoảng trống ở cuối.
dubiousjim

38

Thử cái này:

awk '{ $1=""; $2=""; $3=""; print $0 }'

1
Điều này là tốt vì nó năng động như thế nào. Bạn có thể thêm các cột vào cuối và không phải viết lại các tập lệnh của mình.
MinceMan

1
Điều này chứng tỏ vấn đề chính xác mà câu hỏi đang cố gắng giải quyết bạn chỉ làm ngược lại. Điều gì về in từ trường thứ 100? Lưu ý đề cập đến bạn không đối phó với NFvì vậy bạn bỏ đi dẫn đầu OFS.
Chris Seymour

24

Cách chính xác để làm điều này là sử dụng khoảng RE vì nó cho phép bạn chỉ cần xác định có bao nhiêu trường cần bỏ qua và giữ lại khoảng cách giữa các trường cho các trường còn lại.

Ví dụ: để bỏ qua 3 trường đầu tiên mà không ảnh hưởng đến khoảng cách giữa các trường còn lại với định dạng đầu vào mà chúng ta dường như đang thảo luận trong câu hỏi này chỉ đơn giản là:

$ echo '1   2 3 4   5    6' |
awk '{sub(/([^ ]+ +){3}/,"")}1'
4   5    6

Nếu bạn muốn chứa khoảng trắng ở đầu và khoảng trắng không trống, nhưng lại có FS mặc định, thì đó là:

$ echo '  1   2 3 4   5    6' |
awk '{sub(/[[:space:]]*([^[:space:]]+[[:space:]]+){3}/,"")}1'
4   5    6

Nếu bạn có FS là RE mà bạn không thể phủ định trong một bộ ký tự, trước tiên bạn có thể chuyển đổi nó thành một ký tự (RS là lý tưởng nếu đó là một ký tự đơn vì RS KHÔNG THỂ xuất hiện trong một trường, nếu không, hãy xem xét SUBSEP), sau đó áp dụng phân bổ khoảng RE, sau đó chuyển đổi sang OFS. ví dụ: nếu chuỗi "." được phân tách các trường:

$ echo '1...2.3.4...5....6' |
awk -F'[.]+' '{gsub(FS,RS);sub("([^"RS"]+["RS"]+){3}","");gsub(RS,OFS)}1'
4 5 6

Rõ ràng nếu OFS là một ký tự đơn VÀ nó không thể xuất hiện trong các trường đầu vào, bạn có thể giảm giá trị đó thành:

$ echo '1...2.3.4...5....6' |
awk -F'[.]+' '{gsub(FS,OFS); sub("([^"OFS"]+["OFS"]+){3}","")}1'
4 5 6

Sau đó, bạn gặp phải vấn đề tương tự như với tất cả các giải pháp dựa trên vòng lặp gán lại các trường - các FS được chuyển đổi thành OFS. Nếu đó là một vấn đề, bạn cần phải xem xét hàm patsplit () của GNU awks.


Không hoạt động với tôi (bash 4.1.2 (1) -release, GNU Awk 3.1.7 hoặc bash 3.2.25 (1) -release, GNU Awk 3.1.5) nhưng được tìm thấy ở đây theo cách khác:echo ' This is a test' | awk '{print substr($0, index($0,$3))}'
elysch

2
Không, điều đó sẽ không thành công nếu $ 1 hoặc $ 2 chứa chuỗi mà $ 3 được đặt thành. Ví dụ, hãy thử echo ' That is a test' | awk '{print substr($0, index($0,$3))}'và bạn sẽ thấy rằng số atiền 3 đô la khớp với số tiền abên trong Thatbằng 1 đô la. Trong một phiên bản rất cũ của gawk như bạn có, bạn cần bật các khoảng RE với cờ --re-interval.
Ed Morton

2
Bạn nói đúng, không để ý. Nhân tiện, thực sự đánh giá cao nhận xét của bạn. Nhiều lần muốn sử dụng một regex với "{}" để chỉ định số phần tử và không bao giờ thấy "--re-khoảng" trong người đàn ông. +1 cho bạn.
elysch

1
1là một điều kiện đúng và do đó gọi hành động awk mặc định để in bản ghi hiện tại.
Ed Morton

1
idk nó là chuẩn như thế nào nhưng tôi đã thêm câu trả lời ngay bây giờ.
Ed Morton

10

Khá nhiều câu trả lời hiện có thêm dấu cách ở đầu, dấu cách ở cuối hoặc một số vấn đề về dấu phân tách khác. Để chọn từ trường thứ tư, nơi dấu phân tách là khoảng trắng và dấu phân tách đầu ra là một khoảng trắng, sử dụng awksẽ là:

awk '{for(i=4;i<=NF;i++)printf "%s",$i (i==NF?ORS:OFS)}' file

Để tham số hóa trường bắt đầu, bạn có thể làm:

awk '{for(i=n;i<=NF;i++)printf "%s",$i (i==NF?ORS:OFS)}' n=4 file

Và cũng là trường kết thúc:

awk '{for(i=n;i<=m=(m>NF?NF:m);i++)printf "%s",$i (i==m?ORS:OFS)}' n=4 m=10 file

6
awk '{$1=$2=$3="";$0=$0;$1=$1}1'

Đầu vào

1 2 3 4 5 6 7

Đầu ra

4 5 6 7

4
echo 1 2 3 4 5| awk '{ for (i=3; i<=NF; i++) print $i }'

3
Hoặc để đặt chúng trên cùng một dòng, gán $ 3 đến $ 1, v.v. và sau đó thay đổi NF thành số trường phù hợp. echo 1 2 3 4 5| awk '{ for (i=3; i<=NF; i++) $(i-2)=$i; NF=NF-2; print $0 }'
larsr

Chào bạn @larsr. Dòng lệnh được đề xuất của bạn là câu trả lời đúng duy nhất. Tất cả các câu trả lời khác đều thêm khoảng trắng (đầu hoặc cuối). Xin vui lòng gửi dòng lệnh của bạn trong vòng một câu trả lời mới, tôi sẽ up-bỏ phiếu nó ;-)
olibre

1
Xin chào @sudo_O, tôi đã nói chuyện với @larsr, về dòng lệnh mà anh ấy đề xuất trong nhận xét của mình. Tôi đã dành khoảng năm phút trước khi tìm ra quiproco (hiểu lầm). Tôi đồng ý, câu trả lời @Vetsin sẽ chèn các dòng mới ( ORS) giữa các trường. Xin chúc mừng cho sáng kiến ​​của bạn (Tôi thích câu trả lời của bạn). Chúc mừng
olibre

3

Một cách khác để tránh sử dụng câu lệnh in:

 $ awk '{$1=$2=$3=""}sub("^"FS"*","")' file

Trong awk khi một điều kiện là true, in là hành động mặc định.


Điều này có tất cả các vấn đề @lhf câu trả lời có .. nó chỉ ngắn hơn.
Chris Seymour

Ý kiến ​​rất hay;) Tốt hơn câu trả lời của tôi! (Tôi đã
ủng hộ

Nó phải là: awk '{$1=$2=$3=""}sub("^"OFS"+","")' filecũng như OFS những gì còn lại sau khi thay đổi nội dung $ 1, $ 2 và $ 3.

3

Tôi không thể tin rằng không ai cung cấp vỏ đơn giản:

while read -r a b c d; do echo "$d"; done < file

+1 cho giải pháp tương tự ... Nhưng điều này có thể có vấn đề về hiệu suất nếu filelớn (> 10-30KiB). Đối với các tệp lớn, awkgiải pháp hoạt động tốt hơn.
TrueY

3

Tùy chọn 1 đến 3 có vấn đề với nhiều khoảng trắng (nhưng rất đơn giản). Đó là lý do để phát triển các tùy chọn 4 và 5, xử lý nhiều khoảng trắng mà không có vấn đề gì. Tất nhiên, nếu tùy chọn 4 hoặc 5 được sử dụng với n=0cả hai sẽ bảo toàn bất kỳ khoảng trắng đầu nào nhưn=0 đồng nghĩa với việc không chia tách.

lựa chọn 1

Một giải pháp cắt đơn giản (hoạt động với các dấu phân cách đơn):

$ echo '1 2 3 4 5 6 7 8' | cut -d' ' -f4-
4 5 6 7 8

Lựa chọn 2

Việc buộc một re-calc awk đôi khi giải quyết được vấn đề (hoạt động với một số phiên bản awk) của các khoảng trống ở đầu được thêm vào:

$ echo '1 2 3 4 5 6 7 8' | awk '{ $1=$2=$3="";$0=$0;} NF=NF'
4 5 6 7 8

Lựa chọn 3

Việc in từng trường được định dạng printfsẽ giúp kiểm soát nhiều hơn:

$ echo '    1    2  3     4   5   6 7     8  ' |
  awk -v n=3 '{ for (i=n+1; i<=NF; i++){printf("%s%s",$i,i==NF?RS:OFS);} }'
4 5 6 7 8

Tuy nhiên, tất cả các câu trả lời trước đó đều thay đổi tất cả FS giữa các trường thành OFS. Hãy xây dựng một vài giải pháp cho điều đó.

Lựa chọn 4

Một vòng lặp với con để loại bỏ các trường và dấu phân cách là linh hoạt hơn và không kích hoạt thay đổi FS thành OFS:

$ echo '    1    2  3     4   5   6 7     8  ' |
awk -v n=3 '{ for(i=1;i<=n;i++) { sub("^["FS"]*[^"FS"]+["FS"]+","",$0);} } 1 '
4   5   6 7     8

LƯU Ý: "^ [" FS "] *" là chấp nhận đầu vào có dấu cách ở đầu.

Lựa chọn 5

Hoàn toàn có thể xây dựng một giải pháp không thêm khoảng trắng ở đầu hoặc cuối và bảo toàn khoảng trắng hiện có bằng cách sử dụng hàm gensubtừ GNU awk, như sau:

$ echo '    1    2  3     4   5   6 7     8  ' |
awk -v n=3 '{ print gensub("["FS"]*([^"FS"]+["FS"]+){"n"}","",1); }'
4   5   6 7     8 

Nó cũng có thể được sử dụng để hoán đổi danh sách trường đã cho một số lượng n:

$ echo '    1    2  3     4   5   6 7     8  ' |
  awk -v n=3 '{ a=gensub("["FS"]*([^"FS"]+["FS"]+){"n"}","",1);
                b=gensub("^(.*)("a")","\\1",1);
                print "|"a"|","!"b"!";
               }'
|4   5   6 7     8  | !    1    2  3     !

Tất nhiên, trong trường hợp này, OFS được sử dụng để tách cả hai phần của dòng và khoảng trắng ở cuối của các trường vẫn được in.

Note1: ["FS"]* được sử dụng để cho phép khoảng trắng ở đầu dòng nhập.


Chào BZ Câu trả lời của bạn rất hay. Nhưng tùy chọn 3 không hoạt động trên chuỗi bắt đầu bằng khoảng trắng (ví dụ " 1 2 3 4 5 6 7 8 "). Tùy chọn 4 là tốt nhưng để lại khoảng trắng ở đầu bằng cách sử dụng chuỗi bắt đầu bằng khoảng trắng. Bạn nghĩ nếu điều này có thể sửa chữa được? Bạn có thể sử dụng lệnh echo " 1 2 3 4 5 6 7 8 " | your awk script | sed 's/ /./g;s/\t/->/g;s/^/"/;s/$/"/'để xác minh hàng đầu / giữa / dấu không gian ... Cheers;)
olibre

Xin chào @olibre. Việc lựa chọn 3 không thành công với khoảng trắng là lý do để phát triển các phương án 4 và 5. Phương án 4 chỉ để lại khoảng trắng ở đầu nếu đầu vào có nó n được đặt thành 0 (n = 0). Điều đó tôi tin là câu trả lời chính xác khi không có lựa chọn trường (không có gì để sửa IMO). Chúc mừng.

Được rồi. Cảm ơn vì thông tin bổ sung :-) Vui lòng cải thiện câu trả lời của bạn bằng cách cung cấp những thông tin bổ sung này :-) Chúc mừng
olibre

Perfect :-) What a pity người dùng của bạn bị vô hiệu hóa :-(
olibre

1

Cut có cờ --complement giúp xóa cột dễ dàng (và nhanh chóng). Cú pháp kết quả tương tự với những gì bạn muốn làm - giúp giải pháp dễ đọc / hiểu hơn. Phần bổ sung cũng hoạt động trong trường hợp bạn muốn xóa các cột không liền nhau.

$ foo='1 2 3 %s 5 6 7'
$ echo "$foo" | cut --complement -d' ' -f1-3
%s 5 6 7
$

Bạn có thể giải thích thêm câu trả lời của bạn được không?
Zulu

Chỉnh sửa ở trên có giúp hiểu được không? Vấn đề là sử dụng cờ bổ sung của cắt. Giải pháp phải triển khai nhanh hơn và ngắn gọn hơn các giải pháp dựa trên AWK hoặc perl. Ngoài ra, có thể cắt các cột tùy ý.
Michael Back

1

Giải pháp Perl không thêm khoảng trắng đầu hoặc cuối:

perl -lane 'splice @F,0,3; print join " ",@F' file

@FMảng perl autosplit bắt đầu từ chỉ mục 0trong khi các trường awk bắt đầu bằng$1


Giải pháp Perl cho dữ liệu được phân tách bằng dấu phẩy:

perl -F, -lane 'splice @F,0,3; print join ",",@F' file

Giải pháp Python:

python -c "import sys;[sys.stdout.write(' '.join(line.split()[3:]) + '\n') for line in sys.stdin]" < file


0

Đối với tôi, giải pháp nhỏ gọn và phù hợp nhất với yêu cầu là

$ a='1   2\t \t3     4   5   6 7 \t 8\t '; 
$ echo -e "$a" | awk -v n=3 '{while (i<n) {i++; sub($1 FS"*", "")}; print $0}'

Và nếu bạn có nhiều dòng cần xử lý như tệp foo.txt chẳng hạn , đừng quên đặt lại i về 0:

$ awk -v n=3 '{i=0; while (i<n) {i++; sub($1 FS"*", "")}; print $0}' foo.txt

Cảm ơn diễn đàn của bạn.


0

Vì tôi đã khó chịu với câu trả lời sai đầu tiên được ủng hộ cao nhưng tôi đã tìm đủ để viết một câu trả lời ở đó, và ở đây các câu trả lời sai được đánh dấu như vậy, đây là chút của tôi. Tôi không thích các giải pháp được đề xuất vì tôi không thể thấy lý do gì để đưa ra câu trả lời phức tạp như vậy.

Tôi có một nhật ký mà sau $ 5 với địa chỉ IP có thể có nhiều văn bản hơn hoặc không có văn bản. Tôi cần mọi thứ từ địa chỉ IP đến cuối dòng nếu có bất kỳ thứ gì sau $ 5. Trong trường hợp của tôi, đây là thực tế với một chương trình awk, không phải một awk oneliner vì vậy awk phải giải quyết vấn đề. Khi tôi cố gắng xóa 4 trường đầu tiên bằng cách sử dụng câu trả lời cũ đẹp mắt và được nhiều người ủng hộ nhất nhưng hoàn toàn sai:

echo "  7 27.10.16. Thu 11:57:18 37.244.182.218 one two three" | awk '{$1=$2=$3=$4=""; printf "[%s]\n", $0}'

nó đưa ra phản hồi sai và vô ích (tôi đã thêm [] để chứng minh):

[    37.244.182.218 one two three]

Thay vào đó, nếu các cột có chiều rộng cố định cho đến khi cần đến điểm cắt và awk, thì câu trả lời đúng và khá đơn giản là:

echo "  7 27.10.16. Thu 11:57:18 37.244.182.218 one two three" | awk '{printf "[%s]\n", substr($0,28)}'

tạo ra đầu ra mong muốn:

[37.244.182.218 one two three]

0

Tôi đã tìm thấy khả năng khác này, có lẽ nó cũng có thể hữu ích ...

awk 'BEGIN {OFS=ORS="\t" }; {for(i=1; i<14; i++) print $i " "; print $NF "\n" }' your_file

Lưu ý: 1. Đối với dữ liệu dạng bảng và từ cột $ 1 đến $ 14


0

Sử dụng cắt:

cut -d <The character between characters> -f <number of first column>,<number of last column> <file name>

ví dụ: Nếu bạn có file1chứa:car.is.nice.equal.bmw

Chạy : cut -d . -f1,3 file1 sẽ incar.is.nice


Có vẻ như giải pháp của bạn có thể lạc hậu. Vui lòng xem lại tiêu đề câu hỏi In tất cả * trừ * ba cột đầu tiên
Stefan Crain

-1

Đây không phải là quá xa so với một số câu trả lời trước đó, nhưng giải quyết một số vấn đề:

cols.sh:

#!/bin/bash
awk -v s=$1 '{for(i=s; i<=NF;i++) printf "%-5s", $i; print "" }'

Mà bây giờ bạn có thể gọi với một đối số sẽ là cột bắt đầu:

$ echo "1 2 3 4 5 6 7 8 9 10 11 12 13 14" | ./cols.sh 3 
3    4    5    6    7    8    9    10   11   12   13   14

Hoặc là:

$ echo "1 2 3 4 5 6 7 8 9 10 11 12 13 14" | ./cols.sh 7 
7    8    9    10   11   12   13   14

Đây là 1-indexed; nếu bạn muốn lập chỉ mục bằng 0, hãy sử dụng i=s + 1thay thế.

Hơn nữa, nếu bạn muốn phải đối số cho chỉ mục bắt đầu chỉ mục kết thúc, hãy thay đổi tệp thành:

#!/bin/bash
awk -v s=$1 -v e=$2 '{for(i=s; i<=e;i++) printf "%-5s", $i; print "" }'

Ví dụ:

$ echo "1 2 3 4 5 6 7 8 9 10 11 12 13 14" | ./cols.sh 7 9 
7    8    9

Căn %-5schỉnh kết quả dưới dạng các cột rộng 5 ký tự; nếu điều này là không đủ, hãy tăng số lượng hoặc sử dụng %s(với khoảng trắng) để thay thế nếu bạn không quan tâm đến việc căn chỉnh.


-1

Giải pháp dựa trên AWK printf tránh được vấn đề% và độc nhất ở chỗ nó không trả về gì (không có ký tự trả về) nếu có ít hơn 4 cột để in:

awk 'NF > 3 { for(i=4; i<NF; i++) printf("%s ", $(i)); print $(i) }'

Thử nghiệm:

$ x='1 2 3 %s 4 5 6'
$ echo "$x" | awk 'NF > 3 { for(i=4; i<NF; i++) printf("%s ", $(i)); print $(i) }'
%s 4 5 6
$ x='1 2 3'
$ echo "$x" | awk 'NF > 3 { for(i=4; i<NF; i++) printf("%s ", $(i)); print $(i) }'
$ x='1 2 3 '
$ echo "$x" | awk 'NF > 3 { for(i=4; i<NF; i++) printf("%s ", $(i)); print $(i) }'
$
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.