Costruire percorsi in modo robusto


16

Supponiamo che io abbia diverse variabili in uno script di shell (ad es. In zsh):

FOLDER_1, FOLDER_2, etc.

Queste variabili si riferiscono a cartelle discendenti da /. Ad esempio, se ho un percorso/home/me/stuff/items

le variabili sarebbero:

FOLDER_1='home'
FOLDER_2='me'
FOLDER_3='stuff'

Ora, dì che voglio ricostruire il percorso corrispondente concatenando le variabili. Un modo possibile è costruire il percorso come segue:

PATH=$FOLDER_1/$FOLDER_2/$FOLDER_3/

Tuttavia, supponiamo che alcune delle variabili presentino FOLDER_ibarre rovesciate, mentre altre no (e non sappiamo quale) ad es

FOLDER_1='home'
FOLDER_2='stuff/'
FOLDER_3='items'

La mia domanda è: come potrei costruire il percorso in modo robusto? (ad esempio evitando doppi tagli e aggiungendoli dove devono essere).

Ho pensato che un modo per farlo fosse quello di aggiungere /sempre le coppie di variabili e quindi eliminare tutti i duplicati sed, ma non riesco a farlo funzionare (non sono sicuro che sto gestendo /correttamente sed).

Inoltre, sto reinventando la ruota ? (cioè c'è qualche built-in che lo fa già?).

In definitiva, se le variabili sono in un array , ad esempio FOLDERS, sarebbe possibile farlo senza loop? (o in alternativa, eseguendo il loop ma senza sapere quanti FOLDERSce ne sono nell'array).

Risposte:


12

È possibile utilizzare printfcon un array:

parts=("$FOLDER_1" "$FOLDER_2" "$FOLDER_3");
printf '/%s' "${parts[@]%/}"
# Use "printf -v path" to save it into a variable called "path" instead of printing it

L' %operatore taglia le stringhe finali, in questo caso /. Applicandolo a parts[@], ritaglia ogni membro dell'array separatamente.

La chiave per comprendere questo printftrucco, è questa man 1 printf: "La stringa di formato viene riutilizzata tutte le volte che è necessario per soddisfare gli argomenti".


Il %metodo singolo funziona per la singola barra finale menzionata nel queston. Per soddisfare quando ci sono più barre, ${parts[@]%%/*}funziona. Ecco un link a qualche informazione in più sul problema della barra: Cosa significano le doppie barre nel percorso UNIX? È 'cd dir / subdir // valido ...
Peter.O

2
@fered: /*in questo caso non significa zero o più barre , ma piuttosto una barra seguita da un numero qualsiasi di caratteri. Ciò significa che se il percorso inizia con una barra, il risultato sarà la stringa vuota!
l0b0,

Avevo considerato, come nell'esempio, che ci sarebbero state solo barre finali. Tuttavia, per adattarsi alla possibilità di una (e) extglobshopt -s extglob; ${parts[@]%%/+(/)}
bara

15

La semplice risposta è smettere di preoccuparsi e amare più barre. Le barre multiple hanno lo stesso effetto di una barra singola (tranne per il fatto che un percorso che inizia con //un significato diverso su alcuni sistemi; i livelli di emulazione unix su Windows sono gli unici che posso nominare). È in base alla progettazione e la possibilità di assemblare i nomi dei file senza doversi preoccupare di più barre è stata una parte importante di quella decisione di progettazione.

Per unire gli elementi dell'array, in zsh, è possibile utilizzare il j flag di espansione dei parametri .

dir=${(j:/:)FOLDERS}

Puoi schiacciare le doppie barre mentre ci sei, ma è puramente cosmetico.

setopt extended_glob
dir=${${(j:/:)FOLDERS}//\/\/##/\/}

In ksh e bash, puoi unire un array usando il primo carattere di $IFScome separatore. È quindi possibile schiacciare le barre duplicate. In bash, dovrai fare shopt -s extglobper abilitare i globs ksh nell'ultima riga dello snippet di seguito.

IFS=/
dir="${FOLDERS[*]}"
unset IFS
dir=${dir//\/+(\/)//}

3

Come sednon funziona per te? Prova sed 's|/\+|/|g'dopo la concatenazione o sed 's|/||g'prima.


1

bash 4introdotto il globbing esteso, che consente la corrispondenza delle espressioni regolari nella sostituzione dei parametri ${var....}... È disattivato per impostazione predefinita. Per abilitarlo per il tuo script, imposta semplicemente l'opzione shell extglob ...

Supponendo che $ dir ==/home/me/////////stuff//items

shopt -s extglob; dir="${dir//+(\/)//}"

Valore risultante di $ dir

/home/me/stuff/items  

Ecco alcuni esempi di cose da fare e da non fare: Bash Extended Globbing

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.