Làm cách nào tôi có thể xóa tất cả văn bản sau một ký tự trong bash?


147

Làm cách nào tôi có thể xóa tất cả văn bản sau một ký tự, trong trường hợp này là dấu hai chấm (":"), trong bash? Tôi cũng có thể loại bỏ ruột kết? Tôi không biết làm thế nào để.

Câu trả lời:


134

Một ví dụ có thể hữu ích, nhưng nếu tôi hiểu đúng về bạn, điều này sẽ hoạt động:

echo "Hello: world" | cut -f1 -d":"

Điều này sẽ chuyển đổi "hello: world" thành "hello".


5
cuthoạt động, nhưng câu trả lời của tôi Dennis là tốt hơn và linh hoạt hơn. Có ai biết nếu nó sinh ra một quá trình mới như thế cutnào?
JoBu1324

3
Tốt hơn là sử dụng các tính năng mở rộng tham số tích hợp của Bash hơn là tạo các công cụ con chạy như basenamecut, xem câu trả lời của Dennis bên dưới
Louis Maddox

1
cutcó thể đọc từ stdin, vì vậy tốt hơn là khi bạn có một chuỗi rất dài mà bạn cần xử lý, như nội dung của tệp.
Sahas

1
Và làm thế nào điều này sẽ được áp dụng cho hello: world. Đây là một nửa câu trả lời.
K - Độc tính trong SO đang tăng lên.

Nó có thể được thực hiện bằng cách sử dụng cú pháp trợ cấp cũng như {var /: / ''}, nhưng chỉ hoạt động trong bash ..
Mahesh

263

Trong Bash (và ksh, zsh, dash, v.v.), bạn có thể sử dụng mở rộng tham số %sẽ xóa các ký tự khỏi cuối chuỗi hoặc #sẽ xóa các ký tự khỏi đầu chuỗi. Nếu bạn sử dụng một trong những ký tự đó, chuỗi kết hợp nhỏ nhất sẽ bị xóa. Nếu bạn nhân đôi nhân vật, lâu nhất sẽ bị xóa.

$ a='hello:world'
$ b=${a%:*}
$ echo "$b"
hello
$ a='hello:world:of:tomorrow'
$ echo "${a%:*}"
hello:world:of
$ echo "${a%%:*}"
hello
$ echo "${a#*:}"
world:of:tomorrow
$ echo "${a##*:}"
tomorrow

6
Đây là thao tác chuỗi shell riêng, vì vậy không có quá trình bổ sung nào được sinh ra. Tham chiếu Bash Tham số thay thế , Thao tác chuỗi BashViết kịch bản Bash tốt hơn
Dodzi Dzakuma

@denniswilliamson Làm cách nào tôi có thể xóa 2 ký tự sau khi một chuỗi cụ thể như thế hello:worldsẽ trở thành hello:wobằng cách sử dụng ${a%:*}?
3kstc

Câu trả lời tuyệt vời, cảm ơn rất nhiều, nhưng cũng thật tuyệt khi thêm "${a##*:}"vào chỉ nhận tomorrow=)
avtomaton

1
@openCivilisation: Có lẽ bạn cần sử dụng kết hợp biểu thức chính quy sau đó : a='hello:world:of:tomorrow'; pattern=''^([^:]*:).*$'; [[$ a = ~ $ mẫu]]; tiếng vang "$ {BASH_REMATCH [1]}" `. Điều đó chỉ phù hợp nếu có một dấu hai chấm. Nếu bạn muốn điều đó là tùy chọn, một mẫu khác sẽ được sử dụng. Một lời giải thích về Bash regexes (và regexes nói chung) nằm ngoài phạm vi của những bình luận này. Bạn có thể tìm thấy các câu hỏi khác thảo luận về điều này hoặc đăng bài của riêng bạn.
Tạm dừng cho đến khi có thông báo mới.

1
@ kp123: Đây là ví dụ đầu tiên trong câu trả lời của tôi. Lần thứ hai tôi hiển thị nó (nơi "ngày mai" bị xóa), đó gần như chính xác là tình huống bạn đang hỏi về.
Tạm dừng cho đến khi có thông báo mới.


4
egrep -o '^[^:]*:'

bạn có thể giải thích làm thế nào để giải thích điều này, Cảm ơn bạn.
rɑːdʒɑ

1
egreplà grep với -E. Nó làm cho không có sự khác biệt ở đây từ thường xuyên grep. -ohướng dẫn grep chỉ in ra một phần của dòng khớp với biểu thức. ^neo trận đấu đến đầu một dòng. [^:]*khớp với 0 hoặc nhiều ký tự không phải là :ký tự. :phù hợp với nhân vật :.
cdhowie

Cảm ơn một lần nữa vì lời giải thích
rɑːdʒɑ

3

Giả sử bạn có một đường dẫn với một tệp ở định dạng này:

/dirA/dirB/dirC/filename.file

Bây giờ bạn chỉ muốn đường dẫn bao gồm bốn "/". Kiểu

$ echo "/dirA/dirB/dirC/filename.file" | cut -f1-4 -d"/"

và đầu ra của bạn sẽ là

/dirA/dirB/dirC

Ưu điểm của việc sử dụng cut là bạn cũng có thể cắt thư mục uppest cũng như tệp (trong ví dụ này), vì vậy nếu bạn gõ

$ echo "/dirA/dirB/dirC/filename.file" | cut -f1-3 -d"/"

đầu ra của bạn sẽ là

/dirA/dirB

Mặc dù bạn có thể làm tương tự từ phía bên kia của chuỗi, nhưng nó sẽ không có ý nghĩa nhiều trong trường hợp này như gõ

$ echo "/dirA/dirB/dirC/filename.file" | cut -f2-4 -d"/"

kết quả trong

dirA/dirB/dirC

Trong một số trường hợp khác, trường hợp cuối cùng cũng có thể hữu ích. Lưu ý rằng không có "/" ở đầu đầu ra cuối cùng.


2
Điều gì sẽ xảy ra nếu bạn có một thư mục "/resource/view/admin/users/relationships/posts.blade.php" và bạn muốn cắt bớt mọi thứ sau khi xảy ra LAST của "/", cho rằng bạn KHÔNG biết có bao nhiêu "/" "Các ký tự nằm trong chuỗi. Vì vậy, ở đây tôi muốn đầu ra là "/ tài nguyên / lượt xem / quản trị viên / người dùng / mối quan hệ /" (hoặc thậm chí / tài nguyên / lượt xem / quản trị viên / người dùng / mối quan hệ mà không có dấu gạch chéo). Bạn làm điều đó như thế nào?
kp123

-1

cắt bỏ mọi thứ sau ví dụ cuối cùng của ":"

cat fileListingPathsAndFiles.txt | grep -o '^.*:'

và nếu bạn muốn bỏ cái cuối cùng ":"

cat file.txt | grep -o '^.*:' | sed 's/:$//'

@ kp123: bạn muốn thay thế :bằng /(nơi có dấu hai chấm \/)

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.