Cortando todos os caracteres após o último /

8

Como faço para cortar todos os caracteres após o último '/'?

Este texto

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

deve retornar

xxxx/x/xx/xx/xxxx/x
xxx/xxxx/xxxxx
    
por Josef Klimuk 27.02.2018 / 16:27

7 respostas

10

Se você deseja obter a "parte cortada"

yyy
yyyyy

Você pode usar

sed 's|.*/||' 

por exemplo.

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

saída

yyy
yyyyy

(Nota: Isso usa a habilidade do sed de usar um separador diferente de /, neste caso |, no comando s)

Se você quiser começar o começo da string:

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

Você pode usar

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

por exemplo,

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

saída

xxx/xxxx/xxxxx
xxxx/x/xx/xx/xxxx/x
    
por Félicien 27.02.2018 / 16:30
18

Se você estiver cortando off as extremidades das strings, dirname poderá se encaixar na fatura:

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

Se você estiver tentando isolar a última parte da string, use echo /$(basename "$str") .

$ str=xxxx/x/xx/xx/xxxx/x/yyyyy
$ echo /$(basename "$str")
/yyyyy
$ _
    
por dsstorefile1 27.02.2018 / 16:33
15

Expansão de parâmetro em bash

Você pode usar a expansão de parâmetro em bash , neste caso

  • ${parameter%word} em que word é /*
  • ${parameter##word} em que word é */

Exemplos:

Remover a última parte

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

Isso é descrito em 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.

Remover tudo, exceto a última parte

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

Você pode adicionar uma barra como essa

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

para obter exatamente o que você queria em uma instância específica de acordo com a pergunta editada. Mas a questão foi editada por várias pessoas depois disso e não é fácil saber o que você quer agora.

Isso é descrito em 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.
    
por sudodus 27.02.2018 / 16:33
9

Outra maneira é usar grep para exibir apenas a última barra por linha e o que segue:

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

Explicação:

-o diz grep para mostrar apenas a parte correspondente da linha em vez da linha inteira.

O padrão /[^/]*$ corresponde a uma barra literal / seguida por qualquer caractere, exceto por uma barra [^/] qualquer número de vezes * até o final da linha $ .

    
por Byte Commander 27.02.2018 / 16:37
7

Só porque os outros postaram respostas mais "sensatas", aqui está um tanto bobo:

rev | cut -d/ -f1 | rev

rev inverte os caracteres em cada linha, por ex. abcd/ef/g se torna g/fe/dcba . Então cut corta o primeiro segmento. Finalmente, é revertido novamente.

    
por egmont 27.02.2018 / 17:55
3

Solução clássica com awk , que trata / como separador de campo para entrada e saída e define o último campo para cadeia vazia (que é realmente "dereferência" do número de campos NF variable):

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

Mais curto, como fedorqui apontado nos comentários:

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

A variação disso seria colocar o caminho no ambiente de execução de awk , o que economizará no encanamento, mas tornará awk porção mais detalhada:

mypath="xxx/xxxx/xxxxx/yyy" awk  'BEGIN{OFS=FS="/"; sub(/\/([^\/]*)$/,"",ENVIRON["mypath"]);print(ENVIRON["mypath"]) };'
    
por Sergiy Kolodyazhnyy 28.02.2018 / 03:43
2

Adicionando a resposta do egmont porque a questão foi editada ...

Use - complemento se quiser remover o primeiro campo com -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

Além disso, a questão não é clara sobre o que deve acontecer com entradas que não contenham nenhuma barra.     xxxx = > xxxx ou     xxxx = > nada

    
por Ph3n0x 28.02.2018 / 15:07