Cách cắt cột thứ hai theo chiều dài cho trước


9

Cho đầu vào của mẫu

XY981743    foobarlkasdf saflkas asfZR!sgfad asdSAD asdsadf SAdfasdf46lk lksad bar foolkasjfdrte

Làm thế nào tôi có thể cắt chỉ cột thứ hai? Dấu phân cách là TAB và cột thứ hai phải dài tối đa 75 ký tự.


awk 'BEGIN{OFS=FS="\t"} {$2=substr($2,1,75)}1' file
Nói

Bạn có muốn cắt bớt (xóa các ký tự sau lần thứ 75) hoặc gấp lại (in chúng trên một dòng khác) không? Ngoài ra, các khoảng trắng có nên được tính vào 75 ký tự hay không?
terdon

Câu trả lời:


7

Nếu bạn chỉ muốn in 75 ký tự đầu tiên của cột thứ hai (bao gồm cả khoảng trắng và giả sử chỉ có hai cột trong tệp), bạn có thể thực hiện:

$ perl -pe 's/(\t.{75}).*/$1/' file
XY981743    foobarlkasdf saflkas asfZR!sgfad asdSAD asdsadf SAdfasdf46lk lksad bar fool

Hoặc, với GNU sed:

$ sed 's/\(.*\t.\{75\}\).*/\1/' file
XY981743    foobarlkasdf saflkas asfZR!sgfad asdSAD asdsadf SAdfasdf46lk lksad bar fool

Hoặc là:

$ sed -r 's/(.*\t.{75}).*/\1/' file
XY981743    foobarlkasdf saflkas asfZR!sgfad asdSAD asdsadf SAdfasdf46lk lksad bar fool

Ngoài ra, bạn có thể sử dụng fold, yêu cầu nó cắt ở 91 ký tự đầu tiên (đó là 8 cho mã định danh và 8 ký tự khác cho tab) và chỉ in dòng đầu tiên:

$ fold -w 91 file | head -n1
XY981743    foobarlkasdf saflkas asfZR!sgfad asdSAD asdsadf SAdfasdf46lk lksad bar fool

Nếu tệp của bạn có thể có nhiều hơn 2 cột và bạn chỉ muốn cắt bớt cột thứ hai, bạn có thể làm (mà như tôi vừa nhận thấy, chỉ là một cách viết lại câu trả lời của Stephen ):

$ awk -F"\t" -vOFS="\t" '{$2=substr($2,1,75)}1;' file
XY981743    foobarlkasdf saflkas asfZR!sgfad asdSAD asdsadf SAdfasdf46lk lksad bar fool

Hoặc (lưu ý rằng điều này sẽ bị phá vỡ nếu 75 ký tự đầu tiên của cột thứ 2 có thể được hiểu là một biểu thức chính quy):

$ perl -F"\t" -pale 's/$F[1]/substr($F[1],0,75)/e' file
XY981743    foobarlkasdf saflkas asfZR!sgfad asdSAD asdsadf SAdfasdf46lk lksad bar fool

Những cái đó có thể cắt một cột khác ngoài cột thứ hai. sedLệnh đầu tiên của bạn cũng đang sử dụng GNUism ( \t).
Stéphane Chazelas

@ StéphaneChazelas là ? \tlà một chủ nghĩa GNU? Nghiêm túc? Cách di động để mô tả một tab sau đó là gì?
terdon

1
Chèn nó nguyên văn để xem câu trả lời của tôi. Trình tự thoát duy nhất được công nhận có thể di chuyển trên LHS là \n(và một lần nữa không bên trong [...]có nhiều triển khai), không có trong RHS.
Stéphane Chazelas

@ StéphaneChazelas chết tiệt, cảm ơn. Tôi cũng đã thêm một giải pháp có thể xử lý nhiều cột.
terdon

Điều cuối cùng của bạn perllàm cho rất ít ý nghĩa. Hãy suy nghĩ ví dụ về một đầu vào nhưaba\t.*
Stéphane Chazelas

10

Sử dụng awk, phân chia tệp bằng các tab và xuất trường đầu tiên đầy đủ và 75 ký tự đầu tiên (nhiều nhất) của giây:

awk -F "\t" 'BEGIN { OFS=FS }; { print $1, substr($2, 1, 75); }'

Như được chỉ ra bởi fedorqui , bạn có thể xử lý các tệp có nhiều hơn hai trường bằng cách thay thế các trường bạn cần cắt bớt:

awk -F "\t" 'BEGIN { OFS=FS }; { $2=substr($2, 1, 75); print }'

Bạn có thể áp dụng substrcho nhiều trường bằng cách lặp qua chúng nếu cần thiết.


@ Stéphane, trong trường hợp nào là ;cần thiết thêm ?
Stephen Kitt

Chúng được POSIX yêu cầu. Bây giờ tôi không biết về bất kỳ triển khai nào khi chúng được yêu cầu, nhưng khi tôi hỏi rằng yêu cầu POSIX được nới lỏng, nó đã bị từ chối bởi người duy trì gawk (trong đó tất cả các ví dụ trong tài liệu đều có;).
Stéphane Chazelas

Ah, tốt để biết, cảm ơn! Vì vậy, thông số kỹ thuật và tài liệu chặt chẽ hơn tất cả các triển khai ...
Stephen Kitt

tất cả các triển khai mà tôi biết ít nhất (không quá nhiều). Vấn đề là bỏ qua dấu phân cách làm cho cú pháp không chuẩn. Vì vậy, các triển khai hiện tại và trong tương lai có thể và có quyền bóp nghẹt nó hoặc giới thiệu các tiện ích mở rộng sử dụng nó (ví dụ như xử lý ngoại lệ /pattern/ {action} {exception-handling}chẳng hạn). Bây giờ điều đó sẽ cực kỳ khó xảy ra khi bỏ qua những thứ đó ;là khá phổ biến.
Stéphane Chazelas

4

Có thể / POSIXly với sed:

tab=$(printf '\t')
sed "s/\($tab[^$tab]\{0,75\}\)[^$tab]*/\1/"

Hoặc để cắt bớt mỗi cột:

sed "s/\([^$tab]\{75\}\)[^$tab]*/\1/g"

2

Nếu chỉ có 2 cột:

sed -r 's/^([^\t]*\t)(.{0,75}).*/\1\2/'

{0,75}có nghĩa là chọn từ 0 đến 75 ký tự.
.* là phần bị loại bỏ ngoài char 75.


Nếu có 2 cột trở lên :

sed -r 's/^([^\t]*\t)([^\t]{0,75})[^\t]*(.*)/\1\2\3/' file

[^\t]* là phần bị loại bỏ ngoài char 75.


Lưu ý rằng giả sử GNU sedPOSIXLY_CORRECTkhông có trong môi trường ..
Stéphane Chazelas
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.