estrae parte di una stringa usando bash / cut / split


121

Ho una stringa come questa:

/var/cpanel/users/joebloggs:DNS9=domain.com

Devo estrarre il nome utente ( joebloggs) da questa stringa e memorizzarlo in una variabile.

Il formato della stringa sarà sempre lo stesso ad eccezione di joebloggse domain.comquindi penso che la stringa possa essere divisa due volte usando cut?

La prima divisione sarebbe divisa per :e memorizzeremo la prima parte in una variabile per passare alla seconda funzione di divisione.

La seconda divisione si divide per /e memorizza l'ultima parola ( joebloggs) in una variabile

So come farlo in php usando array e split ma sono un po 'perso in bash.

Risposte:


333

Per estrarre joebloggsda questa stringa in bash utilizzando l'espansione dei parametri senza alcun processo aggiuntivo ...

MYVAR="/var/cpanel/users/joebloggs:DNS9=domain.com" 

NAME=${MYVAR%:*}  # retain the part before the colon
NAME=${NAME##*/}  # retain the part after the last slash
echo $NAME

Non dipende joebloggsdall'essere a una particolare profondità del percorso.


Sommario

Una panoramica di alcune modalità di espansione dei parametri, per riferimento ...

${MYVAR#pattern}     # delete shortest match of pattern from the beginning
${MYVAR##pattern}    # delete longest match of pattern from the beginning
${MYVAR%pattern}     # delete shortest match of pattern from the end
${MYVAR%%pattern}    # delete longest match of pattern from the end

Quindi #significa corrispondenza dall'inizio (pensa a una riga di commento) e %significa dalla fine. Un'istanza significa più breve e due istanze significa più lunga.

Puoi ottenere sottostringhe in base alla posizione utilizzando i numeri:

${MYVAR:3}   # Remove the first three chars (leaving 4..end)
${MYVAR::3}  # Return the first three characters
${MYVAR:3:5} # The next five characters after removing the first 3 (chars 4-9)

Puoi anche sostituire stringhe o pattern particolari usando:

${MYVAR/search/replace}

Il patternè nello stesso formato di file-name corrispondente, in modo *(qualsiasi carattere) è comune, spesso seguite da un simbolo particolare come /o.

Esempi:

Data una variabile come

MYVAR="users/joebloggs/domain.com" 

Rimuovi il percorso lasciando il nome del file (tutti i caratteri fino a una barra):

echo ${MYVAR##*/}
domain.com

Rimuovi il nome del file, lasciando il percorso (elimina la corrispondenza più breve dopo l'ultima /):

echo ${MYVAR%/*}
users/joebloggs

Ottieni solo l'estensione del file (rimuovi tutto prima dell'ultimo punto):

echo ${MYVAR##*.}
com

NOTA: per eseguire due operazioni, non è possibile combinarle, ma è necessario assegnarle a una variabile intermedia. Quindi, per ottenere il nome del file senza percorso o estensione:

NAME=${MYVAR##*/}      # remove part before last slash
echo ${NAME%.*}        # from the new var remove the part after the last period
domain

Non sono sicuro che questo sia un argomento a favore o contro l'uso creativo di grep, ma provalo con VAR = / here / is / a / path: with / a / colon / inside: DNS9 = domain.com
rici

2
Dolce! Ed è fatto all'interno della shell di esecuzione, quindi molto più velocemente di quelli che utilizzano altri comandi.
stolsvik

3
@Fadi Devi cambiare il carattere jolly prima dei due punti e usare #invece di %. Se vuoi solo la parte dopo l'ultimo due punti, usa ${MYVAR##*:}per ottenere la parte dopo i primi due punti, usa${MYVAR#*:}
beroe

4
Amico, non sai quante volte sono tornato a questa risposta. Grazie!
Joel B

1
Bella risposta! Domanda: Se il mio pattern fosse una variabile, lo scriverei in questo modo ${RET##*$CHOP}o in questo modo ${RET##*CHOP}(o in un altro modo)? EDIT: Sembra essere il primo,${RET##*$CHOP}
Ctrl S

43

Definisci una funzione come questa:

getUserName() {
    echo $1 | cut -d : -f 1 | xargs basename
}

E passa la stringa come parametro:

userName=$(getUserName "/var/cpanel/users/joebloggs:DNS9=domain.com")
echo $userName

1
Questa risposta mi ha aiutato a ottenere ciò per cui sono venuto qui. Non ci sono risposte accettate e questa ottiene il mio voto per semplicità.
harperville

1
L'unica correzione che ho dovuto fare nel comando precedente è stata la rimozione di ":", in questo modo echo $1 | cut -d -f 1 | xargs. +1 per ans semplici e ordinate.
Bhushan

20

E sed? Funzionerà con un unico comando:

sed 's#.*/\([^:]*\).*#\1#' <<<$string
  • Il #vengono utilizzati per i divisori regex anziché /poiché la stringa ha /in esso.
  • .*/ afferra la stringa fino all'ultima barra rovesciata.
  • \( .. \)contrassegna un gruppo di cattura. Questo è \([^:]*\).
    • La [^:]dice qualsiasi carattere _except due punti, ed i *mezzi zero o più.
  • .* significa il resto della linea.
  • \1significa sostituire ciò che è stato trovato nel primo (e unico) gruppo di cattura. Questo è il nome.

Ecco la ripartizione della corrispondenza della stringa con l'espressione regolare:

        /var/cpanel/users/           joebloggs  :DNS9=domain.com joebloggs
sed 's#.*/                          \([^:]*\)   .*              #\1       #'

Super bella dissezione!
kyb

11

Utilizzando un singolo sed

echo "/var/cpanel/users/joebloggs:DNS9=domain.com" | sed 's/.*\/\(.*\):.*/\1/'

10

Utilizzando un singolo Awk:

... | awk -F '[/:]' '{print $5}'

Cioè, utilizzando come separatore di campo o /o :, il nome utente è sempre nel campo 5.

Per memorizzarlo in una variabile:

username=$(... | awk -F '[/:]' '{print $5}')

Un'implementazione più flessibile con sedche non richiede che il nome utente sia il campo 5:

... | sed -e s/:.*// -e s?.*/??

Cioè, elimina tutto da :e oltre, quindi elimina tutto fino all'ultimo /. sedprobabilmente è anche più veloce di awk, quindi questa alternativa è decisamente migliore.

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.