Cắt tất cả các ký tự sau lần cuối /


14

Làm cách nào để cắt tất cả các ký tự sau '/' cuối cùng?

Văn bản này

xxxx/x/xx/xx/xxxx/x/yyyyy
xxx/xxxx/xxxxx/yyy

nên trở về

xxxx/x/xx/xx/xxxx/x
xxx/xxxx/xxxxx

Câu hỏi hay, tôi mới nhận ra rằng chúng tôi đã không hiểu câu hỏi theo cùng một cách
Félicien

3
Các lệnh basenamedirnamelàm điều này đã.
Michael Hampton

Tôi không nghĩ chỉnh sửa số 5 cho câu hỏi là chính xác. Sử dụng từ "cắt" có thể mơ hồ; Nếu bạn cắt một cái gì đó, bạn có vứt bỏ phần đó, hoặc bạn chỉ giữ lại phần đó? Tuy nhiên, từ ngữ trước "và bỏ qua những gì trước /" là không rõ ràng. Điều này đã được thay đổi thành đối diện của nó.
egmont

@egmont từ "cắt" tự nó đã được chuyển từ bản gốc: "Tôi chỉ cần cắt các ký tự sau lần cuối /" trở thành "Làm thế nào để tôi cắt tất cả các ký tự sau '/' cuối cùng?" đó là một sự thay đổi của cụm từ hợp lý giữ ý nghĩa, IMO. Nếu bất cứ điều gì, tôi cảm thấy phần "bỏ qua những gì là ..." mơ hồ: các ví dụ dường như giữ lại những gì trước /. Ví dụ, làm cho nó rõ ràng, dù sao.
muru

@muru Tôi đang nói về chỉnh sửa đã thêm các ví dụ, không phải chỉnh sửa của bạn.
egmont

Câu trả lời:


15

Nếu bạn muốn có được "phần bị cắt"

yyy
yyyyy

Bạn có thể dùng

sed 's|.*/||' 

ví dụ.

echo "xxx/xxxx/xxxxx/yyy" | sed 's|.*/||'
echo "xxxx/x/xx/xx/xxxx/x/yyyyy" | sed 's|.*\/||'

đầu ra

yyy
yyyyy

(Lưu ý: Điều này sử dụng khả năng của sed để sử dụng một dấu phân tách khác với /, trong trường hợp này |, trong lệnh s)


Nếu bạn muốn có được sự bắt đầu của chuỗi:

xxx/xxxx/xxxxx
xxxx/x/xx/xx/xxxx/x

Bạn có thể dùng

sed 's|\(.*\)/.*|\1|'

ví dụ.

echo "xxx/xxxx/xxxxx/yyy" | sed 's|\(.*\)/.*|\1|'
echo "xxxx/x/xx/xx/xxxx/x/yyyyy" | sed 's|\(.*\)/.*|\1|'

đầu ra

xxx/xxxx/xxxxx
xxxx/x/xx/xx/xxxx/x

6
Xin chào, trong trường hợp này, bạn có thể thay đổi dấu phân cách, ví dụ #thay vì /. Ngoài ra, bạn có thể sử dụng tùy chọn -rnếu bạn không muốn thoát `\` mỗi ký tự đặc biệt : sed -r 's#(^.*)/.*$#\1#'.
pa4080

1
Tôi đã gửi một chỉnh sửa đề xuất để sử dụng | thay vì /. Nếu bạn không thích nó, tôi khuyên bạn nên "từ chối và chỉnh sửa" nó, và thay đổi "bắt đầu" thành "bắt đầu". (Từ chối + Chỉnh sửa, vì như vậy nó sẽ không được chấp thuận bởi robo-người phê duyệt Ngoài ra, chỉ cần cuộn thay đổi trở lại nếu nó đã bị phê duyệt và bạn không thích nó..)
Martin Bonner hỗ trợ Monica

18

Nếu bạn đang cắt giảm các đầu của chuỗi, dirnamecó thể phù hợp với những hóa đơn:

$ dirname xxxx/x/xx/xx/xxxx/x/yyyyy
xxxx/x/xx/xx/xxxx/x
$ _

Nếu bạn đang cố gắng cách ly phần cuối của chuỗi, hãy sử dụng echo /$(basename "$str").

$ str=xxxx/x/xx/xx/xxxx/x/yyyyy
$ echo /$(basename "$str")
/yyyyy
$ _

3
Thành thật mà nói, tại sao bất cứ ai cũng sẽ đề nghị hoặc chấp nhận một câu trả lời liên quan đến sed (hoặc awk, hoặc bất kỳ phương pháp tương tự nào khác) thay vì chỉ sử dụng các tiện ích được cài đặt với HĐH là ngoài tôi.
Auspex

@Auspex Tôi đoán nó đơn giản là vì dirnamebasenamekhông được biết đến rộng rãi, nhưng sedawklà.
Volker Siegel

@Auspex: Vì dirname và tên cơ sở không hoạt động trên stdin, do đó cat text | basenamesẽ không hoạt động. Vì vậy, một giải pháp thích hợp cho câu hỏi của OP sử dụng dirnamebasenamesẽ liên quan, xargsv.v.
Pod

16

Mở rộng tham số trong bash

Bạn có thể sử dụng mở rộng tham số trong bash, trong trường hợp này

  • ${parameter%word}nơi word/*
  • ${parameter##word}nơi word*/

Ví dụ:

Xóa phần cuối cùng

$ asdf="xxx/xxxx/xxxxx/yyy"
$ echo ${asdf%/*}
xxx/xxxx/xxxxx

Điều này được mô tả trong man bash:

${parameter%word}
${parameter%%word}
      Remove matching suffix pattern.  The word is expanded to produce
      a pattern just as in pathname expansion.  If the pattern matches
      a  trailing portion of the expanded value of parameter, then the
      result of the expansion is the expanded value of parameter  with
      the  shortest  matching  pattern (the ``%'' case) or the longest
      matching pattern (the ``%%'' case) deleted.  If parameter  is  @
      or  *,  the  pattern  removal operation is applied to each posi‐
      tional parameter in turn, and the  expansion  is  the  resultant
      list.   If  parameter is an array variable subscripted with @ or
      *, the pattern removal operation is applied to  each  member  of
      the array in turn, and the expansion is the resultant list.

Xóa tất cả ngoại trừ phần cuối cùng

$ asdf="xxx/xxxx/xxxxx/yyy"
$ echo ${asdf##*/}
yyy

Bạn có thể thêm một dấu gạch chéo như vậy

$ echo /${asdf##*/}
/yyy

để có được chính xác những gì bạn muốn tại một trường hợp cụ thể theo câu hỏi đã chỉnh sửa. Nhưng câu hỏi đã được một số người chỉnh sửa sau đó và không dễ để biết bạn muốn gì bây giờ.

Điều này được mô tả trong man bash:

${parameter#word}
${parameter##word}
      Remove matching prefix pattern.  The word is expanded to produce
      a pattern just as in pathname expansion.  If the pattern matches
      the  beginning of the value of parameter, then the result of the
      expansion is the expanded value of parameter with  the  shortest
      matching  pattern  (the ``#'' case) or the longest matching pat‐
      tern (the ``##'' case) deleted.  If parameter is  @  or  *,  the
      pattern  removal operation is applied to each positional parame‐
      ter in turn, and the expansion is the resultant list.  If param‐
      eter  is  an array variable subscripted with @ or *, the pattern
      removal operation is applied to each  member  of  the  array  in
      turn, and the expansion is the resultant list.

10

Một cách khác là sử dụng grepđể chỉ hiển thị dấu gạch chéo cuối cùng trên mỗi dòng và bất cứ điều gì theo sau nó:

$ grep -o '/[^/]*$' example.txt
/yyy
/yyyyy

Giải trình:

-onói grepvới chỉ hiển thị phần phù hợp của dòng thay vì toàn bộ dòng.

Mẫu này /[^/]*$khớp với một dấu gạch chéo /theo sau bởi bất kỳ ký tự nào ngoại trừ một dấu gạch chéo [^/]bất kỳ số lần nào *cho đến hết dòng $.


8

Chỉ vì những người khác đã đăng thêm câu trả lời của sane, đây là một câu trả lời hơi ngớ ngẩn:

rev | cut -d/ -f1 | rev

revđảo ngược các ký tự trong mỗi dòng, ví dụ abcd/ef/gtrở thành g/fe/dcba. Sau đó cutcắt ra đoạn đầu tiên. Cuối cùng, nó lại đảo ngược.


2
Bất chấp sự không tỉnh táo của câu trả lời này, đặc biệt là vì hệ thống ống nước vỏ, tôi thích câu trả lời này :) Tiếp tục rung chuyển, +1
Sergiy Kolodyazhnyy

Đồng ý - không lành mạnh, nhưng xấu xa!
Volker Siegel

3

Giải pháp cổ điển với awk, được coi /là dấu tách trường cho cả đầu vào và đầu ra và đặt trường cuối cùng thành chuỗi rỗng (thực sự là "hội nghị" của số lượng NFbiến trường ):

$ echo "xxx/xxxx/xxxxx/yyy"|awk  'BEGIN{OFS=FS="/"};{$NF="";print $0}'
xxx/xxxx/xxxxx/

Ngắn gọn hơn, như fedorqui đã chỉ ra trong các ý kiến:

$ echo "xxx/xxxx/xxxxx/yyy"|awk  'BEGIN{OFS=FS="/"};NF--'
xxx/xxxx/xxxxx/

Sự thay đổi trên đó sẽ là đưa đường dẫn vào awkmôi trường thực thi, điều này sẽ tiết kiệm được hệ thống ống nước nhưng làm cho awkphần dài hơn:

mypath="xxx/xxxx/xxxxx/yyy" awk  'BEGIN{OFS=FS="/"; sub(/\/([^\/]*)$/,"",ENVIRON["mypath"]);print(ENVIRON["mypath"]) };'

1
Quá dài dòng, tại sao không chỉ NF--? Bằng cách này bạn avoud printbla bla.
fedorqui

3

Thêm vào câu trả lời của egmont vì câu hỏi đã được chỉnh sửa ...

Sử dụng - compuity nếu bạn muốn xóa trường đầu tiên bằng -f1 .

echo "xxxx/x/xx/xx/xxxx/x/yyyyy"|rev|cut -d/ -f1 --complement|rev
xxxx/x/xx/xx/xxxx/x

echo "xxxx/x/xx/xx/xxxx/x/yyyyy"|rev|cut -d/ -f1|rev
yyyyy

Ngoài ra, câu hỏi không rõ ràng về những gì sẽ xảy ra với đầu vào không chứa bất kỳ dấu gạch chéo nào. xxxx => xxxx hoặc xxxx => không có gì


Bạn có thể đề xuất một chỉnh sửa cho nó: askubfox.com/posts/1010356/edit
muru

@muru OP là 1 người dùng. Không chỉnh sửa đặc quyền được cấp ở mức 2k? Askubfox.com/help/privileges/edit
Sergiy Kolodyazhnyy

@SergiyKolodyazhnyy bất cứ ai cũng có thể đề xuất chỉnh sửa.
muru

+1 - Tôi đã không nhận thấy --complementtùy chọn trước đó và trang man là hình tròn. Bổ sung có nghĩa là bổ sung. Tôi tìm thấy một hướng dẫn cắt đẹp bao gồm nó tại yourownlinux.com/2015/05/ Từ Nó giống như -vtrong grep. Hãy cho tôi tất cả mọi thứ trừ những gì phù hợp.
Joe

2
-f2-là một hình thức đơn giản hơn cho -f1 --complement.
egmont
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.