Vorrei cancellare l'ultimo carattere di una stringa, ho provato questo piccolo script:
#! /bin/sh
t="lkj"
t=${t:-2}
echo $t
ma stampa "lkj", cosa sto facendo di sbagliato?
Vorrei cancellare l'ultimo carattere di una stringa, ho provato questo piccolo script:
#! /bin/sh
t="lkj"
t=${t:-2}
echo $t
ma stampa "lkj", cosa sto facendo di sbagliato?
Risposte:
In una shell POSIX, la sintassi ${t:-2}
significa qualcosa di diverso: si espande al valore di t
if t
è impostato e non nullo, e altrimenti al valore 2
. Per tagliare un singolo carattere in base all'espansione dei parametri, la sintassi che probabilmente desideri è${t%?}
Si noti che in ksh93
, bash
o zsh
, ${t:(-2)}
o ${t: -2}
(notare lo spazio) sono legali come espansione di sottostringa ma probabilmente non sono ciò che si desidera, poiché restituiscono la sottostringa a partire da una posizione di 2 caratteri dalla fine (ovvero rimuove il primo carattere i
di stringa ijk
).
Vedi la sezione Espansione dei parametri Shell del Manuale di riferimento di Bash per maggiori informazioni:
${parameter%word}
rimuove la corrispondenza del pattern suffisso più breve word
- vedere la sezione Espansione dei parametri diman bash
Con la versione bash
4.2 e successive, puoi fare:
${var::-1}
Esempio:
$ a=123
$ echo "${a::-1}"
12
Si noti che per i più vecchi bash
(ad esempio, bash 3.2.5
su OS X), è necessario lasciare spazi tra e dopo i due punti:
${var: : -1}
bash
versione 4.2-alpha e successive, peccato che la versione a cui ho accesso sia precedente. : - /
${var:offset:lenght}
stata aggiunta solo in bash 4.2
. Forse OSX aggiunge la propria patch per bash
.
per rimuovere gli ultimi n
caratteri da una riga che non utilizza sed
OR awk
:
> echo lkj | rev | cut -c (n+1)- | rev
quindi ad esempio puoi eliminare l'ultimo carattere one character
usando questo:
> echo lkj | rev | cut -c 2- | rev
> lk
dalla rev
manpage:
DESCRIZIONE
L'utilità rev copia i file specificati nell'output standard, invertendo l'ordine dei caratteri in ogni riga. Se non viene specificato alcun file, viene letto l'input standard.
AGGIORNARE:
se non conosci la lunghezza della stringa, prova:
$ x="lkj"
$ echo "${x%?}"
lk
Usando sed dovrebbe essere veloce come
sed 's/.$//'
Il tuo unico eco è quindi echo ljk | sed 's/.$//'
.
Usando questo, la stringa di 1 riga potrebbe essere di qualsiasi dimensione.
Alcune opzioni a seconda della shell:
t=${t%?}
t=`expr " $t" : ' \(.*\).'`
t=${t[1,-2]}
t=${t:0:-1}
t=${t:0:${#t}-1}
t=${t/%?}
t=${t/~(E).$/}
@ {t=$1} ~~ $t *?
Si noti che mentre tutti dovrebbero spogliare l'ultimo carattere , scoprirete che alcune implementazioni (quelle che non supportano i caratteri multi-byte) rimuovono invece l'ultimo byte (quindi probabilmente corromperebbe l'ultimo carattere se fosse multi-byte ).
La expr
variante presuppone $t
che non finisca con più di un carattere di nuova riga. Restituirà anche uno stato di uscita diverso da zero se la stringa risultante finisce per essere 0
(o 000
o anche -0
con alcune implementazioni). Potrebbe anche dare risultati imprevisti se la stringa contiene caratteri non validi.
t=${t%?}
non è Bourne ma al giorno d'oggi non ti imbatterai in una shell Bourne. ${t%?}
funziona in tutti gli altri però.
fish
è in corso di elaborazione. 2.3.0 che ha introdotto il string
builtin non è stato rilasciato al momento del Q&A. Con la versione su cui sto testando, è necessario string replace -r '(?s).\z' '' -- $t
(e mi aspetto che vorrebbero cambiarlo, dovrebbero cambiare le bandiere che passano a PCRE) o più contorte. Si occupa anche male dei personaggi newline e so che stanno pianificando di cambiare anche quello.
La risposta più portatile e più breve è quasi certamente:
${t%?}
Funziona in bash, sh, ash, trattino, busybox / ash, zsh, ksh, ecc.
Funziona utilizzando l'espansione dei parametri della shell della vecchia scuola. In particolare, %
specifica di rimuovere il più piccolo suffisso di corrispondenza del parametro t
che corrisponde al modello glob ?
(cioè: qualsiasi carattere).
Vedere "Rimuovi modello suffisso più piccolo" qui per una spiegazione (molto) più dettagliata e più sfondo. Vedi anche i documenti per la tua shell (ad es . man bash
:) sotto "espansione dei parametri".
Come nota a margine, se si desidera rimuovere invece il primo carattere, è necessario utilizzare ${t#?}
, poiché le #
corrispondenze dalla parte anteriore della stringa (prefisso) anziché dalla parte posteriore (suffisso).
Vale anche la pena notare che entrambi %
e #
hanno %%
e ##
versioni, che corrispondono alla versione più lunga del modello dato anziché alla più breve. Entrambi ${t%%?}
e ${t##?}
farebbero lo stesso del loro singolo operatore in questo caso, però (quindi non aggiungere l'inutile carattere extra). Questo perché il ?
modello dato corrisponde solo a un singolo carattere. Mescola in a *
con alcuni caratteri jolly e le cose diventano più interessanti con %%
e ##
.
Comprendere le espansioni dei parametri, o almeno conoscere la loro esistenza e sapere come cercarle, è incredibilmente utile per scrivere e decifrare script di shell di molti gusti. Le espansioni di parametri spesso sembrano voodoo di shell arcane per molte persone perché ... beh ... sono voodoo di shell arcane (anche se abbastanza ben documentate se si sa cercare "espansione di parametri"). Sicuramente bello avere nella cintura degli attrezzi quando sei bloccato in un guscio, però.
t=lkj
echo ${t:0:${#t}-1}
Si ottiene una sottostringa da 0 alla lunghezza della stringa -1. Si noti tuttavia che questa sottostrazione è specifica bash e non funzionerà su altre shell.
Ad esempio, dash
non è in grado di analizzare nemmeno
echo ${t:0:$(expr ${#t} - 1)}
Ad esempio, su Ubuntu /bin/sh
èdash
Puoi anche usare head
per stampare tutto tranne l'ultimo carattere.
$ s='i am a string'
$ news=$(echo -n $s | head -c -1)
$ echo $news
i am a strin
Ma sfortunatamente alcune versioni di head
non includono l' -
opzione principale . Questo è il caso di head
ciò che viene fornito con OS X.
Solo per completare alcuni possibili utilizzi di puro bash:
#!/bin/bash
# Testing substring removal
STR="Exemple string with trailing whitespace "
echo "'$STR'"
echo "Removed trailing whitespace: '${STR:0:${#STR}-1}'"
echo "Removed trailing whitespace: '${STR/%\ /}'"
La prima sintassi prende una sottostringa da una stringa, la sintassi è
Per la seconda, nota il segno, che significa "dalla fine della linea" e la sintassi è
${STRING:OFFSET:LENGTH}
%
${STRING/PATTERN/SUBSTITUTION}
E qui ci sono due forme più brevi di quanto sopra menzionato
echo "Removed trailing whitespace: '${STR::-1}'"
echo "Removed trailing whitespace: '${STR%\ }'"
Qui notate di nuovo il %
segno, che significa 'Rimuovi (cioè sostituisci con' ') il modello abbinato più breve (qui rappresentato dallo spazio di escape ' \ ' dalla fine del PARAMETRO - qui chiamato STR