Como posso remover todo o texto após um caractere no bash?

147

Como posso remover todo o texto após um caractere, neste caso, dois pontos (":"), no bash? Também posso remover o cólon? Eu não tenho idéia de como.

Nathan
fonte

Respostas:

135

Um exemplo pode ter sido útil, mas se eu entendi corretamente, isso funcionaria:

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

Isso converterá "olá: mundo" em "olá".

Eldad Mor
fonte
5
cutfunciona, mas a resposta de Dennis é melhor e mais flexível. Alguém sabe se gera um novo processo como cut?
JoBu1324
3
É melhor usar expansão de parâmetros built-in do Bash dispõe de gerar subshells executando ferramentas como basenamee cut, ver a resposta de Dennis abaixo
Louis Maddox
1
cutpode ler do stdin, por isso é melhor, especialmente quando você tem uma sequência muito longa que precisa processar, como o conteúdo de um arquivo.
Sahas
1
E como isso seria aplicado hello: world. Isso é meia resposta.
K - A toxicidade no SO está crescendo.
Isso pode ser feito usando a sintaxe subsitution também como {var /: / ''}, mas só funciona em bash ..
Mahesh
264

No Bash (e ksh, zsh, dash, etc.), você pode usar a expansão de parâmetros com a %qual removerá os caracteres do final da string ou os #caracteres do início da string. Se você usar um único desses caracteres, a menor string correspondente será removida. Se você dobrar o personagem, o mais longo será removido.

$ 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
Pausado até novo aviso.
fonte
6
Isso é manipulação nativa de strings de shell, portanto, nenhum processo adicional será gerado. Referência Bash Parâmetro Substituição , Bash Manipulação de Strings e melhor Bash Scripting
Dodzi Dzakuma
@denniswilliamson Como eu poderia excluir 2 caracteres após uma sequência específica como hello:worldse tornar hello:wousando ${a%:*}?
3kstc
Grande resposta, muito obrigado, mas será bom para também adicionar "${a##*:}"para recebendo apenas tomorrow=)
avtomaton
1
@openCivilisation: Você provavelmente precisará usar a correspondência de expressão regular, então: a='hello:world:of:tomorrow'; pattern=''^([^:]*:).*$'; [[$ a = ~ $ padrão]]; eco "$ {BASH_REMATCH [1]}" `. Isso corresponde apenas se houver dois pontos. Se você deseja que isso seja opcional, um padrão diferente teria que ser usado. Uma explicação das expressões regulares do Bash (e das expressões regulares em geral) está além do escopo desses comentários. Você pode encontrar outras perguntas que discutam isso ou publique as suas.
Pausado até novo aviso.
1
@ kp123: É o primeiro exemplo da minha resposta. Na segunda vez em que o mostro (onde "amanhã" é removido), é quase exatamente a situação que você está perguntando.
Pausado até novo aviso.
9
$ echo 'hello:world:again' |sed 's/:.*//'
hello
sk8asd123
fonte
4
egrep -o '^[^:]*:'
cdhowie
fonte
você pode explicar como interpretar isso, obrigado.
Decreto
1
egrepé grep com -E. Aqui não faz diferença do normal grep. -oinstrui o grep a imprimir apenas a parte da linha que corresponde à expressão. ^ancora a partida no início de uma linha. [^:]*corresponde a zero ou mais caracteres que não são o :caractere. :corresponde ao personagem :.
Cdhowie
Mais uma vez obrigado pela explicação #
30216
3

Digamos que você tenha um caminho com um arquivo neste formato:

/dirA/dirB/dirC/filename.file

Agora você deseja apenas o caminho que inclui quatro "/". Tipo

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

e sua saída será

/dirA/dirB/dirC

A vantagem de usar o cut é que você também pode cortar o diretório mais atual e o arquivo (neste exemplo); portanto, se você digitar

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

sua saída seria

/dirA/dirB

Embora você possa fazer o mesmo do outro lado da string, não faria muito sentido nesse caso, como digitar

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

resulta em

dirA/dirB/dirC

Em alguns outros casos, o último caso também pode ser útil. Lembre-se de que não há "/" no início da última saída.

Nico Feulner
fonte
2
E se você tiver um diretório "/resources/views/admin/users/relationships/posts.blade.php" e quiser truncar tudo após a ÚLTIMA ocorrência do "/", desde que você NÃO saiba quantos "/ "caracteres estão na string. Então, aqui eu gostaria que a saída fosse "/ resources / views / admin / users / relationships /" (ou mesmo / resources / views / admin / users / relationships sem a barra final). Como você faria isso?
kp123
-1

aparar tudo após a última instância de ":"

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

e se você quiser largar esse último ":"

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

@ kp123: você gostaria de substituir :por /(onde o cólon sed deve estar \/)

S Hunter Simpson
fonte