Come ottenere il carattere in una determinata posizione di una stringa nello script di shell?


22

Come ottenere il carattere in una determinata posizione di una stringa nello script di shell?

Risposte:


36

In bash con "Parameter Expansion" $ {parametro: offset: lunghezza}

$ var=abcdef
$ echo ${var:0:1}
a
$ echo ${var:3:1}
d

Modifica: senza espansione dei parametri (non molto elegante, ma è quello che mi è venuto prima)

$ charpos() { pos=$1;shift; echo "$@"|sed 's/^.\{'$pos'\}\(.\).*$/\1/';}
$ charpos 8 what ever here
r



Puoi anche impostare l'offset 'dalla fine' in questo modoecho ${var: -2:1}
Vassilis,

Questa sintassi deriva da ksh93 ed è supportata anche da zshe mksh.
Stéphane Chazelas,

6

L'alternativa all'espansione dei parametri è expr substr

substr STRING POS LENGTH
    substring of STRING, POS counted from 1

Per esempio:

$ expr substr hello 2 1
e

fresco, avrebbe dovuto controllare expr più a fondo.
forcefsck

1
Mentre questo sembra funzionare con l'espr da core GNU GNU, substrnon è incluso nell'espr da FreeBSD, NetBSD o OS X. Questa non è una soluzione portatile.
ghoti,

@ghoti, nota che in substrorigine non è un'estensione GNU. L'implementazione originale è exprarrivata da PWB Unix alla fine degli anni '70 e aveva substr(ma non :).
Stéphane Chazelas,

@ StéphaneChazelas, grazie per l'aggiunta di una prospettiva storica. :) Anche se sono abbastanza sicuro che l'uso di PWB non sia rilevante per l'OP, è sempre divertente tenere traccia delle funzionalità e delle modifiche nel corso dei decenni. GNU tende ad essere il default di molte persone, ma in generale, penso che eviterei di usare opzioni che non sono chiaramente POSIX e che sono note per mancare ai principali unici.
ghoti,

5

cut -c

Se la variabile non contiene newline puoi fare:

myvar='abc'
printf '%s\n' "$myvar" | cut -c2

uscite:

b

awk substr è un'altra alternativa POSIX che funziona anche se la variabile ha newline:

myvar="$(printf 'a\nb\n')" # note that the last newline is stripped by
                           # the command substitution
awk -- 'BEGIN {print substr (ARGV[1], 3, 1)}' "$myvar"

uscite:

b

printf '%s\n'è per evitare problemi con i caratteri di escape: /programming//a/40423558/895245 ad esempio:

myvar='\n'
printf '%s\n' "$myvar" | cut -c1

output \come previsto.

Vedi anche: /programming/1405611/extracting-first-two-characters-of-a-string-shell-scripting

Testato su Ubuntu 19.04.


printf '%s' "$myvar" | cut -c2non è POSIX poiché l'output di printfnon è testo se non $myvartermina con un carattere di nuova riga. Suppone altrimenti che la variabile non contenga caratteri di nuova riga poiché cuttaglia ogni riga del suo input.
Stéphane Chazelas,

L' awkuno sarebbe più efficiente e affidabile conawk -- 'BEGIN {print substr (ARGV[1], 2, 1)}' "$myvar"
Stéphane Chazelas

Si noti che con le versioni attuali di GNU cut, che non funziona per i caratteri multi-byte (lo stesso per mawk o busybox awk)
Stéphane Chazelas,

@ StéphaneChazelas grazie per i punti. Non ho capito cosa intendi nel primo: vuoi dire che printf 'abc '| cut -c2è sbagliato perché no \n(questo non lo so), o che il comando fallirà se myvar ha newline (questo sono d'accordo)?
Ciro Santilli 6 改造 中心 法轮功 六四 事件

1
Il comportamento di cutnon è specificato se l'input non è di testo (sebbene cutsiano necessarie implementazioni per gestire linee o lunghezza arbitraria). L'output di printf abcnon è testo in quanto non termina in un carattere di nuova riga. In pratica a seconda della realizzazione, se il tubo che per cut -c2, si ottiene uno b, b<newline>o niente del tutto. Dovresti printf 'abc\n' | cut -c2ottenere un comportamento specificato da POSIX (necessario per l'output b<newline>)
Stéphane Chazelas,

1

Con zsho yash, useresti:

$ text='€$*₭£'
$ printf '%s\n' "${text[3]}"
*

(in zsh, puoi accorciarlo a printf '%s\n' $text[3]).


0

Puoi usare il comando taglia. Per ottenere la 3a posizione:

echo "SAMPLETEXT" | cut -c3

Controlla questo link http://www.folkstalk.com/2012/02/cut-command-in-unix-linux-examples.html

( Casi avanzati ) Tuttavia, anche la modifica di IFS è una buona cosa, specialmente quando l'input potrebbe contenere spazi. Solo in quel caso, usa quello qui sotto

saveifs=$IFS
IFS=$(echo -en "\n\b")
echo "SAMPLETEXT" | cut -c3
IFS=$saveifs

Non riesco a vedere come IFSentrerebbe in gioco il codice che hai pubblicato.
Kusalananda
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.