Sto cercando di rimuovere parte del percorso in una stringa. Ho il percorso:
/path/to/file/drive/file/path/
Voglio rimuovere la prima parte /path/to/file/drive
e produrre l’output:
file/path/
Nota: ho diversi percorsi in un ciclo while, con lo stesso /path/to/file/drive
in tutti, ma sto solo cercando il “come” per rimuovere la stringa desiderata.
Ho trovato alcuni esempi, ma non riesco a farli funzionare:
echo /path/to/file/drive/file/path/ | sed 's:/path/to/file/drive:\2:' echo /path/to/file/drive/file/path/ | sed 's:/path/to/file/drive:2'
\2
è la seconda parte della stringa e sto chiaramente facendo qualcosa di sbagliato … forse c’è un modo più semplice?
Puoi anche usare l’espansione delle variabili della shell POSIX per fare ciò.
path=/path/to/file/drive/file/path/ echo ${path#/path/to/file/drive/}
La parte #..
rimuove una stringa di corrispondenza principale quando la variabile viene espansa; questo è particolarmente utile se le stringhe sono già in variabili di shell, come se si stesse usando un ciclo for
. Puoi anche eliminare le stringhe corrispondenti (ad esempio un’estensione) dalla fine di una variabile, usando %...
Vedi la pagina man bash
per i dettagli cruenti.
Se si desidera rimuovere un determinato NUMERO di componenti del percorso, è necessario utilizzare il cut
con -d'/'
. Ad esempio, se path=/home/dude/some/deepish/dir
:
Per rimuovere i primi due componenti:
# (Add 2 to the number of components to remove to get the value to pass to -f) $ echo $path | cut -d'/' -f4- some/deepish/dir
Per mantenere i primi due componenti:
$ echo $path | cut -d'/' -f-3 /home/dude
Per rimuovere gli ultimi due componenti ( rev
inverte la stringa):
$ echo $path | rev | cut -d'/' -f4- | rev /home/dude/some
Per mantenere gli ultimi tre componenti:
$ echo $path | rev | cut -d'/' -f-3 | rev some/deepish/dir
Oppure, se si desidera rimuovere tutto prima di un particolare componente, sed
funzionerebbe:
$ echo $path | sed 's/.*\(some\)/\1/g' some/deepish/dir
O dopo un particolare componente:
$ echo $path | sed 's/\(dude\).*/\1/g' /home/dude
È ancora più semplice se non vuoi mantenere il componente che stai specificando:
$ echo $path | sed 's/some.*//g' /home/dude/
E se vuoi essere coerente puoi uguagliare anche la barra finale:
$ echo $path | sed 's/\/some.*//g' /home/dude
Ovviamente, se combini diverse barre, devi cambiare il delimitatore sed
:
$ echo $path | sed 's!/some.*!!g' /home/dude
Nota che questi esempi usano tutti i percorsi assoluti, dovrai giocare per farli funzionare con percorsi relativi.
Se non si desidera eseguire l’hardcode della parte che si sta rimuovendo:
$ s='/path/to/file/drive/file/path/' $ echo ${s#$(dirname "$(dirname "$s")")/} file/path/
Un modo per farlo con sed è
echo /path/to/file/drive/file/path/ | sed 's:^/path/to/file/drive/::'
Usare ${path#/path/to/file/drive/}
come suggerito dal male otto è certamente il modo tipico / migliore per farlo, ma dato che ci sono molti suggerimenti sed, vale la pena sottolineare che sed è eccessivo se si è lavorando con una stringa fissa. Puoi anche fare:
echo $PATH | cut -b 21-
Per scartare i primi 20 caratteri. Allo stesso modo, puoi usare ${PATH:20}
in bash o $PATH[20,-1]
in zsh.
Se vuoi rimuovere le prime N parti del percorso , potresti ovviamente usare N chiamate a basename
, come nella risposta di Glenn , ma probabilmente è più facile usare il globbing:
path=/path/to/file/drive/file/path/ echo "${path#*/*/*/*/*/}" # file/path/
In particolare, ${path#*/*/*/*/*/}
significa “ritorno $path
meno il prefisso più breve che contiene 5 barre” .
Pure bash, senza hard coding la risposta
basenames() { local d="${2}" for ((x=0; x<"${1}"; x++)); do d="${d%/*}" done echo "${2#"${d}"/}" }