Schneiden aller Zeichen nach dem letzten /


13

Wie schneide ich alle Zeichen nach dem letzten '/'?

Dieser Text

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

sollte zurückkehren

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

Gute Frage, ich habe gerade festgestellt, dass wir die Frage nicht auf die gleiche Weise verstanden haben
Félicien

3
Die Befehle basenameund dirnamemach das schon.
Michael Hampton

Ich denke nicht, dass die Bearbeitung von # 5 der Frage korrekt war. Die Verwendung des Wortes "Schnitt" kann mehrdeutig sein. Wenn Sie etwas schneiden, werfen Sie diesen Teil weg oder behalten Sie nur das? Der bisherige Wortlaut "und wegzulassen, was vor dem / steht" war jedoch eindeutig. Dies wurde in das Gegenteil geändert.
Egmont

@egmont das Wort "cut" selbst wurde vom Original übernommen: "Ich muss nur die Zeichen nach dem letzten /schneiden" wurde zu "Wie schneide ich alle Zeichen nach dem letzten '/'?" Das ist eine Änderung der Formulierung, die die Bedeutung vernünftigerweise beibehält, IMO. Wenn überhaupt, fühlte ich den Teil "weglassen, was ist ..." mehrdeutig: Die Beispiele scheinen zu behalten, was vor dem ist /. Das Beispiel macht es trotzdem klar.
Muru

@muru Ich spreche von der Bearbeitung, die die Beispiele hinzugefügt hat, nicht von Ihrer Bearbeitung.
Egmont

Antworten:


15

Wenn Sie das "geschnittene Teil" erhalten möchten

yyy
yyyyy

Sie können verwenden

sed 's|.*/||' 

z.B.

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

Ausgabe

yyy
yyyyy

(Hinweis: Hierbei wird die Fähigkeit von sed verwendet, im Befehl s ein anderes Trennzeichen als /, in diesem Fall |, zu verwenden.)


Wenn Sie den Anfang der Zeichenfolge erhalten möchten:

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

Sie können verwenden

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

z.B.

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

Ausgabe

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

6
Hallo, in diesem Fall können Sie beispielsweise das Trennzeichen #anstelle von ändern /. Sie können die Option auch verwenden, -rwenn Sie nicht jedem Sonderzeichen entkommen möchten : sed -r 's#(^.*)/.*$#\1#'.
pa4080

1
Ich habe einen Änderungsvorschlag zur Verwendung von | eingereicht Anstatt von /. Wenn es Ihnen nicht gefällt, schlage ich vor, dass Sie es "ablehnen und bearbeiten" und "Anfang" in "Anfang" ändern. (Ablehnen + Bearbeiten, da es auf diese Weise nicht von Robo-Genehmigern genehmigt wird. Alternativ können Sie die Änderung einfach zurücksetzen, wenn sie genehmigt wurde und Ihnen nicht gefallen hat.)
Martin Bonner unterstützt Monica am

18

Wenn Sie schneiden aus den Enden der Saiten, dirnamekönnte die Rechnung passen:

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

Wenn Sie versuchen, den letzten Teil der Zeichenfolge zu isolieren, verwenden Sie echo /$(basename "$str").

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

3
Ehrlich gesagt ist es mir ein Rätsel, warum jemand eine Antwort mit sed (oder awk oder einer anderen ähnlichen Methode) vorschlagen oder akzeptieren würde, anstatt nur die mit dem Betriebssystem installierten Dienstprogramme zu verwenden.
Auspex

@Auspex Ich würde vermuten, es liegt einfach daran dirnameund basenameist nicht allgemein bekannt, aber sedund awksind.
Volker Siegel

@Auspex: Da dirname und basename auf stdin nicht funktionieren, funktionieren sie daher cat text | basenamenicht. Also eine richtige Lösung für OPs Frage mit dirnameund basenamewürde beinhalten xargsusw.
Pod

16

Parametererweiterung in bash

bashIn diesem Fall können Sie die Parametererweiterung in verwenden

  • ${parameter%word}wo wordist/*
  • ${parameter##word}wo wordist*/

Beispiele:

Entfernen Sie den letzten Teil

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

Dies ist beschrieben in 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.

Entfernen Sie alle außer dem letzten Teil

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

Sie können einen Schrägstrich wie diesen hinzufügen

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

um genau das zu bekommen, was Sie an einer bestimmten Instanz gemäß der bearbeiteten Frage wollten. Aber die Frage wurde danach von mehreren Personen bearbeitet und es ist nicht einfach zu wissen, was Sie jetzt wollen.

Dies ist beschrieben in 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

Eine andere Möglichkeit besteht darin grep, nur den letzten Schrägstrich pro Zeile anzuzeigen und was auch immer darauf folgt:

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

Erläuterung:

-oweist grepan, nur den passenden Teil der Zeile anstelle der gesamten Zeile anzuzeigen.

Das Muster /[^/]*$entspricht einem wörtlichen Schrägstrich, /gefolgt von einem beliebigen Zeichen, mit Ausnahme eines Schrägstrichs, [^/]der *bis zum Ende der Zeile beliebig oft verwendet wird $.


8

Nur weil andere "vernünftigere" Antworten gepostet haben, ist hier eine etwas dumme:

rev | cut -d/ -f1 | rev

revkehrt die Zeichen in jeder Zeile um, zB abcd/ef/gwird g/fe/dcba. Dann cutschneidet das erste Segment aus. Endlich ist es wieder umgekehrt.


2
Trotz der Unklarheit dieser Antwort, besonders wegen der Rohrleitungen, mag ich diese Antwort :) Schaukeln Sie weiter, +1
Sergiy Kolodyazhnyy

Einverstanden - nicht gesund, aber schlecht!
Volker Siegel

3

Klassische Lösung mit awk, die /sowohl für die Eingabe als auch für die Ausgabe als Feldtrennzeichen behandelt und das letzte Feld auf eine leere Zeichenfolge setzt (was wirklich eine "Dereferenzierung" der Anzahl der NFvariablen Felder bedeutet ):

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

Kürzer, wie Fedorqui in den Kommentaren betonte :

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

Eine Variation davon wäre, den Pfad in awkdie Ausführungsumgebung einzufügen, was die Installation spart, aber den awkTeil ausführlicher macht:

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

1
Zu ausführlich, warum nicht einfach NF--? Auf diese Weise können Sie das printbla bla erkennen.
Fedorqui

3

Hinzufügen zu Egmonts Antwort, da die Frage bearbeitet wurde ...

Verwenden Sie --complement, wenn Sie das erste Feld mit -f1 entfernen möchten .

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

Außerdem ist die Frage nicht ganz klar, was mit Eingaben geschehen soll, die keine Schrägstriche enthalten. xxxx => xxxx oder xxxx => nichts


Sie können eine Änderung
vorschlagen

@muru OP ist 1 Wiederholungsbenutzer. Wird das Bearbeitungsrecht nicht bei 2k gewährt? askubuntu.com/help/privileges/edit
Sergiy Kolodyazhnyy

@SergiyKolodyazhnyy Jeder kann Änderungen vorschlagen.
Muru

+1 - Ich hatte die --complementOption vorher nicht bemerkt und die Manpage ist kreisförmig. Komplement bedeutet Komplement. Ich habe ein schönes Schnitt-Tutorial gefunden, das es unter yourownlinux.com/2015/05/ behandelt. Es ist wie -vin grep. Gib mir alles außer dem, was zusammen passt.
Joe

2
-f2-ist eine einfachere Form für -f1 --complement.
Egmont
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.