Qual è il modo più semplice per rimuovere una barra finale da ogni parametro?


98

Qual è il modo più semplice per rimuovere una barra finale da ogni parametro nell'array "$ @", in modo che rsyncle directory vengano copiate per nome?

rsync -a --exclude='*~' "$@" "$dir"

Il titolo è stato cambiato per chiarimenti. Per comprendere i commenti e le risposte su più barre finali, vedere la cronologia delle modifiche.


Risposte:


160

È possibile utilizzare l' ${parameter%word}espansione descritta in dettaglio qui . Ecco un semplice script di test che dimostra il comportamento:

#!/bin/bash

# Call this as:
#   ./test.sh one/ two/ three/ 
#
# Output:
#  one two three

echo ${@%/}

35
+1: Per essere molto pedante, rimuoverai un singolo taglio, non tutti i tagli finali. Per rimuovere un numero qualsiasi di barre finali:shopt -s extglob; echo "${@%%+(/)}"
— glenn jackman

24
Attenzione: potresti non voler rimuovere le barre finali in tutti i casi. Se "/" viene fornito come argomento, la rimozione della barra finale avrà ... conseguenze sfortunate.
— Gordon Davisson

13
PROTIP: Combina tr -s /con regex variabile per rimuovere le barre ripetute, quindi rimuovere la barra finale. ad esempioDIR=$(echo //some///badly/written///dir////// | tr -s /); DIR=${DIR%/}
— Dave

1
Veramente? Ad un prompt di bash, corri set -- one///// two// three four/; shopt -s extglob; echo "${@%%+(/)}"e dimmi cosa vedi
— glenn jackman

1
@twalberg Apprezzo i "protips" che non sono solo risposte alternative alla domanda di OP nei thread dei commenti.
— Kyle Strand

39

La risposta accettata taglierà UNA barra finale.

Un modo per tagliare più barre finali è questo:

VALUE=/looks/like/a/path///

TRIMMED=$(echo $VALUE | sed 's:/*$::')

echo $VALUE $TRIMMED

Quali uscite:

/looks/like/a/path/// /looks/like/a/path

1
Non dimenticare di citare le tue variabili, nel caso contengano spazi: TRIMMED=$(echo "$VALUE" | sed 's:/*$::')
— tetsujin

1
In realtà questo non è necessario all'interno del $()costrutto. Tuttavia è anche innocuo :) quindi probabilmente è una buona pratica usare le virgolette doppie in "$VALUE"modo da non dover decidere quando e quando non usare le virgolette doppie.
— Chris Johnson

Qualche modo per combinare questo con un'acquisizione precedente? Voglio rimuovere il protocollo e (se presente) la barra finale da un URL ma echo "https://www.example.com/foo/" | sed -e 's|https*://\(.*\)/*$|\1|'non funziona (poiché il gruppo di cattura corrisponde anche alla barra finale, immagino). Posso farlo con due comandi: echo "https://www.example.com/foo/" | sed -e 's|https*://\(.*\)$|\1|' -e 's|/*$||'ma ti chiedevi se si potesse fare con uno?
— Adam

Questa risposta ha funzionato meglio per me con un file di input molto grande. Un semplice sed 's:/*$::' < in.txt > out.txtfa il lavoro in pochi secondi
— MitchellK

22

Questo funziona per me: ${VAR%%+(/)}

Come descritto qui http://wiki.bash-hackers.org/syntax/pattern

Potrebbe essere necessario impostare l'opzione di shell extglob. Non riesco a vederlo abilitato per me ma funziona ancora


2
Per interrogare un'impostazione: shopt extglobsenza opzioni
— glenn jackman

Questo è Extended Pattern Language e devi impostarlo extglob.
— ingyhere

1
Questo non funziona sulla bash incorporata di Mac OS X. La soluzione di Sean Bright sopra fa:${VAR%/}
— Alec Jacobson

13

realpathrisolve un dato percorso. Tra le altre cose rimuove anche le barre finali. Da usare -sper evitare di seguire i collegamenti simulati

DIR=/tmp/a///
echo $(realpath -s $DIR)
# output: /tmp/a

1
Richiede l'esistenza di tutti i nodi nel percorso tranne l'ultimo. Se l'utente inserisce un percorso inesistente, realpathfallirà.
— Livio

2
@Livy realpath --canonicalize-missingfunziona in modo assolutamente corretto con qualsiasi parte inesistente del percorso
— maoizm

e realpath manca su alcune piattaforme :-(
— Mark Ribau

8

Cordiali saluti, ho aggiunto queste due funzioni al mio in .bash_profilebase alle risposte trovate su SO. Come ha detto Chris Johnson, tutte le risposte che utilizzano ${x%/}rimuovono solo una barra, queste funzioni faranno quello che dicono, spero che questo sia utile.

rem_trailing_slash() {
    echo "$1" | sed 's/\/*$//g'
}

force_trailing_slash() {
    echo "$(rem_trailing_slash "$1")/"
}

4

In zsh puoi usare il :amodificatore.

export DIRECTORY='/some//path/name//'

echo "${DIRECTORY:a}"

=> /some/path/name

Funziona come realpathma non fallisce con file / directory mancanti come argomento.

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.