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 tif 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, basho 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 idi 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 bash4.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.5su OS X), è necessario lasciare spazi tra e dopo i due punti:
${var: : -1}
bashversione 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 ncaratteri da una riga che non utilizza sedOR awk:
> echo lkj | rev | cut -c (n+1)- | rev
quindi ad esempio puoi eliminare l'ultimo carattere one characterusando questo:
> echo lkj | rev | cut -c 2- | rev
> lk
dalla revmanpage:
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 exprvariante presuppone $tche 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 000o anche -0con 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 stringbuiltin 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 tche 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, dashnon è in grado di analizzare nemmeno
echo ${t:0:$(expr ${#t} - 1)}
Ad esempio, su Ubuntu /bin/shèdash
Puoi anche usare headper 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 headnon includono l' -opzione principale . Questo è il caso di headciò 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