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.