Come posso rimuovere tutto il testo dopo un carattere in bash?


147

Come posso rimuovere tutto il testo dopo un carattere, in questo caso i due punti (":"), in bash? Posso rimuovere anche i due punti? Non ho idea di come.

Risposte:


135

Un esempio potrebbe essere stato utile, ma se ti avessi capito correttamente, avrebbe funzionato:

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

Questo trasformerà "ciao: mondo" in "ciao".


5
cutfunziona, ma la risposta di I Dennis è migliore e più flessibile. Qualcuno sa se genera un nuovo processo come cut?
JoBu1324,

3
È meglio utilizzare le funzionalità di espansione dei parametri integrate di Bash piuttosto che generare strumenti di esecuzione di subshells come basenamee cut, vedere la risposta di Dennis di seguito
Louis Maddox

1
cutpuò leggere da stdin, quindi è meglio soprattutto quando hai una stringa molto lunga che devi elaborare, come il contenuto di un file.
Sahas,

1
E come verrebbe applicato questo hello: world. Questa è una mezza risposta.
K - La tossicità in SO sta crescendo.

Può essere fatto usando la sintassi di sostituzione anche come {var /: / ''}, ma funziona solo in bash ..
Mahesh

265

In Bash (e ksh, zsh, trattino, ecc.), È possibile utilizzare l'espansione dei parametri con %cui verranno rimossi i caratteri dalla fine della stringa o #che rimuoveranno i caratteri dall'inizio della stringa. Se si utilizza uno di questi caratteri, verrà rimossa la stringa di corrispondenza più piccola. Se raddoppi il personaggio, il più lungo verrà rimosso.

$ 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
Questa è la manipolazione nativa della stringa di shell, quindi non verranno generati processi aggiuntivi. Sostituzione dei parametri di Bash di riferimento , manipolazione delle stringhe di Bash e script di Bash migliori
Dodzi Dzakuma

@denniswilliamson Come ho potuto eliminare 2 caratteri dopo che una stringa specifica come hello:worlddiventerà hello:wousando ${a%:*}?
3kstc,

Ottima risposta, grazie mille, ma sarà bello aggiungere anche "${a##*:}"per ottenere solo tomorrow=)
avtomaton

1
@openCivilisation: probabilmente avete bisogno di usare corrispondenza di espressioni regolari, allora: a='hello:world:of:tomorrow'; pattern=''^([^:]*:).*$'; [[$ a = ~ $ pattern]]; echo "$ {BASH_REMATCH [1]}" `. Ciò corrisponde solo se sono presenti due punti. Se si desidera che sia facoltativo, è necessario utilizzare un modello diverso. Una spiegazione delle regex di Bash (e delle regex in generale) va oltre lo scopo di questi commenti. Puoi trovare altre domande che ne discutono o pubblicare le tue.
In pausa fino a nuovo avviso.

1
@ kp123: è il primo esempio nella mia risposta. La seconda volta che lo mostro (dove viene rimosso "domani"), è quasi esattamente la situazione che stai chiedendo.
In pausa fino a nuovo avviso.


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

puoi spiegare come interpretarlo, grazie.
rʒɑdʒɑ,

1
egrepè grep con -E. Non fa differenza qui dal normale grep. -oindica a grep di stampare solo la parte della riga corrispondente all'espressione. ^fissa la corrispondenza all'inizio di una riga. [^:]*corrisponde a zero o più caratteri che non sono il :personaggio. :corrisponde al personaggio :.
cdhowie,

Grazie ancora per la spiegazione
rɑːdʒɑ

3

Supponiamo che tu abbia un percorso con un file in questo formato:

/dirA/dirB/dirC/filename.file

Ora vuoi solo il percorso che include quattro "/". genere

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

e il tuo output sarà

/dirA/dirB/dirC

Il vantaggio di usare cut è che puoi anche tagliare la directory più alta e il file (in questo esempio), quindi se scrivi

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

il tuo output sarebbe

/dirA/dirB

Anche se puoi fare lo stesso dall'altro lato della stringa, in questo caso non avrebbe molto senso digitare

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

risultati in

dirA/dirB/dirC

In alcuni altri casi, anche l'ultimo caso potrebbe essere utile. Ricorda che non c'è un "/" all'inizio dell'ultima uscita.


2
Che cosa succede se si dispone di una directory "/resources/views/admin/users/relationships/posts.blade.php" e si desidera troncare tutto dopo l'ULTIMA occorrenza del "/", dato che NON si sa quanti "/ "i caratteri sono nella stringa. Quindi qui vorrei che l'output fosse "/ risorse / visualizzazioni / admin / utenti / relazioni /" (o anche / risorse / visualizzazioni / amministratore / utenti / relazioni senza la barra finale). Come lo faresti?
kp123,

-1

tagliare tutto dopo l'ultima istanza di ":"

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

e se volessi eliminare l'ultimo ":"

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

@ kp123: vorresti sostituirlo :con /(dove dovrebbe essere il colon sed \/)

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.