Sử dụng không gian như một dấu phân cách với lệnh cắt


328

Tôi muốn sử dụng không gian như một dấu phân cách với cutlệnh.

Tôi có thể sử dụng cú pháp nào cho việc này?


42
không đúng sự thật, trang dành cho người cắt không giải thích điều này và nói chung, không có nhiều thông tin
ChúZeiv

2
Ngoài ra, "cắt thông tin" không cải thiện trong trường hợp này.
người đàn ông không gian cardiff

3
@ mkuity0 nếu tôi nhớ lại, tôi đã trả lời một bình luận đã bị xóa, nó đã bỏ qua câu hỏi này như được trả lời trong trang nam, theo ý kiến ​​của tôi là "không đúng sự thật", bất kể đó là lý do chính đáng cho nó hoặc không - bây giờ, trong khi tôi thừa nhận rằng có thể có một lý do chính đáng cho việc thiếu thông tin này, tôi vẫn nghĩ rằng tài liệu mà không có ví dụ sử dụng thông thường ít nhất là gây khó chịu, khi không hoàn toàn vô dụng
ChúZeiv

3
@UncleZeiv Hiểu rồi; cảm ơn đã làm rõ; đưa ra sự quan tâm trong câu hỏi này, thật công bằng khi cho rằng mantrang không đủ. Chúng ta hãy xem: " -d delimSử dụng delimlàm ký tự phân cách trường thay vì ký tự tab." (BSD cut, nhưng phiên bản GNU và thông số POSIX khá giống nhau). Sử dụng shell để gọi cut- trường hợp điển hình - do đó yêu cầu bạn phải biết cách thường vượt qua khoảng trắng dưới dạng đối số bằng cú pháp shell , được cho là không phải cutlà công việc của trang man. Tuy nhiên, các ví dụ trong thế giới thực luôn giúp ích và trang man GNU thiếu chúng.
mkuity0

4
mặc dù câu trả lời được chọn là đúng về mặt kỹ thuật, hãy xem xét chọn câu trả lời gần đây và toàn diện hơn bởi @ mkuity0 làm câu trả lời chính tắc để nó lọc lên đầu.
David LeBauer

Câu trả lời:


367
cut -d ' ' -f 2

Trong đó 2 là số trường của trường được phân tách bằng dấu cách bạn muốn.


2
bạn có thể nói cắt để sử dụng bất kỳ số lượng của một ký tự nào đó làm dấu phân cách, như trong RegEx không? ví dụ: bất kỳ số lượng không gian nào, ví dụ \ s +
lưỡng cư

3
@foampile Không, tôi không tin bạn có thể.
Jonathan Hartley

6
Bạn không thể sử dụng regexes với cut, nhưng bạn có thể cutscố gắng "khắc phục" tất cả các cutgiới hạn: github.com/arielf/cut
arielf

bạn có thể có được tất cả các trường phân định không gian thứ ba? như thế nào cut -d ' ' -f 3,6,9,12,15,18mà không phải ghi rõ từng số?
Monocito

168

Thông thường nếu bạn sử dụng không gian làm dấu phân cách, bạn muốn coi nhiều khoảng trắng là một, bởi vì bạn phân tích đầu ra của một lệnh sắp xếp một số cột với khoảng trắng. (và tìm kiếm google cho tôi dẫn đến đây)

Trong trường hợp này, một cutlệnh duy nhất là không đủ và bạn cần sử dụng:

tr -s ' ' | cut -d ' ' -f 2

Hoặc là

awk '{print $2}'

2
Cảm ơn việc sử dụng ví dụ awk, chỉ những gì tôi cần.
spazm

44

Để bổ sung cho các câu trả lời hiện có, hữu ích; mẹo đội mũ cho QZ Hỗ trợ khuyến khích tôi đăng câu trả lời riêng:

Hai cơ chế riêng biệt được sử dụng ở đây:

  • (a) liệu cut bản thân có yêu cầu dấu phân cách (không gian, trong trường hợp này) được chuyển cho -dtùy chọn là một đối số riêng biệt hoặc liệu có thể chấp nhận để nối trực tiếp vào đó hay không -d.

  • (b) cách shell thường phân tích các đối số trước khi chuyển chúng đến lệnh được gọi.

(a) được trả lời bằng một trích dẫn từ hướng dẫn POSIX cho các tiện ích (nhấn mạnh của tôi)

Nếu SYNOPSIS của tiện ích tiêu chuẩn hiển thị tùy chọn có đối số tùy chọn bắt buộc [...], ứng dụng tuân thủ sẽ sử dụng các đối số riêng cho tùy chọn đó và đối số tùy chọn . Tuy nhiên , việc triển khai tuân thủ cũng sẽ cho phép các ứng dụng chỉ định tùy chọn và đối số tùy chọn trong cùng một chuỗi đối số mà không can thiệp các ký tự .

Nói cách khác: Trong trường hợp này, -dđối số tùy chọn là bắt buộc , bạn có thể chọn có chỉ định dấu phân cách là :

  • (s) EITHER: một đối số riêng
  • (d) HOẶC: như một giá trị được gắn trực tiếp vào-d .

Khi bạn đã chọn (d) hoặc (d), đó là phân tích cú pháp chuỗi ký tự của trình bao - (b) - đó là vấn đề:

  • Với (các) phương pháp tiếp cận , tất cả các hình thức sau đây là THIẾT BỊ:

    • -d ' '
    • -d " "
    • -d \<space> # <space> used to represent an actual space for technical reasons
  • Với cách tiếp cận (d) , tất cả các hình thức sau đây là THIẾT BỊ:

    • -d' '
    • -d" "
    • "-d "
    • '-d '
    • d\<space>

Sự tương đương được giải thích bằng cách xử lý chuỗi ký tự của shell :

Tất cả các giải pháp trên đều dẫn đến cùng một chuỗi (trong mỗi nhóm) theo thời gian cutsẽ thấy chúng :

  • (s) : cutxem -d, như là đối số của chính nó , theo sau là một đối số riêng có chứa dấu cách - không có dấu ngoặc kép hoặc \tiền tố!.

  • (d) : cutthấy -d cộng với dấu cách - không có dấu ngoặc kép hoặc \tiền tố! - như một phần của cùng một lập luận.

Lý do các biểu mẫu trong các nhóm tương ứng cuối cùng giống hệt nhau là gấp đôi, dựa trên cách shell phân tích chuỗi ký tự :

  • Vỏ cho phép theo nghĩa đen được xác định như là thông qua một cơ chế gọi là trích dẫn , có thể mất nhiều hình thức :
    • chuỗi trích dẫn đơn : nội dung bên trong '...'được lấy theo nghĩa đen và tạo thành một đối số duy nhất
    • chuỗi được trích dẫn kép : nội dung bên trong "..."cũng tạo thành một đối số duy nhất , nhưng phải tuân theo phép nội suy (mở rộng các tham chiếu biến như $var, thay thế lệnh ( $(...)hoặc `...`) hoặc mở rộng số học ( $(( ... ))).
    • \- trích dẫn các ký tự riêng lẻ : một ký tự\ đứng trước làm cho ký tự đó được hiểu là một nghĩa đen.
  • Trích dẫn được bổ sung bằng cách loại bỏ trích dẫn , có nghĩa là một khi trình bao đã phân tích cú pháp một dòng lệnh, nó sẽ loại bỏ các ký tự trích dẫn khỏi các đối số (kèm theo '...'hoặc "..."hoặc các \trường hợp) - do đó, lệnh được gọi không bao giờ nhìn thấy các ký tự trích dẫn .

36

Bạn cũng có thể nói:

cut -d\  -f 2

Lưu ý rằng có hai khoảng trắng sau dấu gạch chéo ngược.


30
Người biết rằng '\' thoát khỏi nhân vật tiếp theo sẽ rất cẩn thận để lưu ý những gì xảy ra tiếp theo. Sử dụng '\' để thoát các ký tự khoảng trắng như thế này là một thành ngữ rất phổ biến.
Jonathan Hartley

3
@Jonathan Hartley thường là hầu hết các mã không thể đọc được :)
Luca Borrione

1
Từ quan điểm linux / unix, \ là nỗ lực đầu tiên của tôi và nó đã hoạt động. Tôi đồng ý rằng nó ít rõ ràng hơn khi so sánh với ' ', nhưng tôi chắc chắn nhiều người rất vui khi đọc nó ở đây như là sự trấn an hành vi. Để hiểu rõ hơn, vui lòng xem bình luận của @ mkuity0 bên dưới.
tresf

@JonathanHartley chỉnh sửa: "người ích kỷ biết rằng '\' thoát khỏi nhân vật tiếp theo và cho rằng mọi người khác cũng biết điều đó". Đối với các dự án cá nhân, điều này không áp dụng, nhưng trong cài đặt nhóm, giả định đó là một điều rất nguy hiểm (và có khả năng tốn kém).
Eduard Nicodei

1
@EduardNicodei ơi tôi đồng ý. Chúng tôi đã nói về những người đọc mã ("ai thông báo ...?"), Không phải tác giả. Nhưng ngoài ra, ở một số đội, bạn có thể đảm nhận một mức độ thành thạo nhất định. Phụ thuộc vào môi trường.
Jonathan Hartley

5

Tôi mới phát hiện ra rằng bạn cũng có thể sử dụng "-d ":

cut "-d "

Kiểm tra

$ cat a
hello how are you
I am fine
$ cut "-d " -f2 a
how
am

1
Thật vậy - hay '-d '.
mkuity0

3
Lưu ý rằng từ cut's quan điểm tất cả những điều sau đây là giống hệt nhau: "-d ", '-d ', -d" ", -d' ', và -d\<space>: mọi hình thức trực tiếp append đối số tùy chọn (một không gian) để lựa chọn ( -d) và kết quả trong cùng một chuỗi chính xác bởi thời điểm đó cutnhìn thấy chúng: a single đối số chứa d theo sau là khoảng
trắng

1
@ câu trả lời mklement0 nên được các câu trả lời. Nó là toàn diện nhất trên trang này (mặc dù nó là một bình luận).
tresf

@QZSupport: Tôi đánh giá cao tình cảm và sự khích lệ - nó đã truyền cảm hứng cho tôi để đăng câu trả lời của riêng mình với thông tin bổ sung.
mkuity0

1
Lol khám phá mê hoặc!
Harry

4

Bạn không thể thực hiện dễ dàng với việc cắt nếu dữ liệu có nhiều khoảng trắng. Tôi đã tìm thấy nó hữu ích để bình thường hóa đầu vào để xử lý dễ dàng hơn. Một mẹo nhỏ là sử dụng sed để bình thường hóa như dưới đây.

echo -e "foor\t \t bar" | sed 's:\s\+:\t:g' | cut -f2  #bar

3

scut , một tiện ích giống như cắt (thông minh hơn nhưng tôi đã tạo ra chậm hơn) có thể sử dụng bất kỳ regex perl nào làm mã thông báo phá vỡ. Phá vỡ trên khoảng trắng là mặc định, nhưng bạn cũng có thể phá vỡ các biểu thức đa char, biểu thức thay thế, v.v.

scut -f='6 2 8 7' < input.file  > output.file

vì vậy lệnh trên sẽ phá vỡ các cột trên khoảng trắng và trích xuất các cols (dựa trên 0) 6 2 8 7 theo thứ tự đó.


0

Tôi có một câu trả lời (tôi thừa nhận câu trả lời hơi khó hiểu) liên quan đến sed, các biểu thức chính quy và các nhóm bắt giữ:

  • \S* - từ đầu tiên
  • \s* - dấu phân cách
  • (\S*) - từ thứ hai - bị bắt
  • .* - phần còn lại của dòng

Như một sedbiểu thức, nhóm bắt giữ cần phải được thoát, tức là \(\).

Trả \1về một bản sao của nhóm bị bắt, tức là từ thứ hai.

$ echo "alpha beta gamma delta" | sed 's/\S*\s*\(\S*\).*/\1/'
beta

Khi bạn nhìn vào câu trả lời này, nó hơi khó hiểu, và, bạn có thể nghĩ, tại sao phải bận tâm? Chà, tôi hy vọng rằng một số người, có thể đi "Aha!" và sẽ sử dụng mẫu này để giải quyết một số vấn đề trích xuất văn bản phức tạp với một sedbiểu thức.

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.