Ad esempio, dato:
USCAGoleta9311734.5021-120.1287855805
Voglio estrarre solo:
US
Ad esempio, dato:
USCAGoleta9311734.5021-120.1287855805
Voglio estrarre solo:
US
Risposte:
Probabilmente il metodo più efficiente, se stai usando la bash
shell (e sembra che tu lo sia, in base ai tuoi commenti), è usare la variante della sottostringa dell'espansione dei parametri:
pax> long="USCAGol.blah.blah.blah"
pax> short="${long:0:2}" ; echo "${short}"
US
Saranno short
i primi due caratteri di long
. Se long
è più corto di due caratteri, short
sarà identico.
Questo metodo in-shell di solito è migliore se lo farai molto (come 50.000 volte per rapporto come hai menzionato) poiché non c'è alcun sovraccarico di creazione del processo. Tutte le soluzioni che utilizzano programmi esterni soffriranno di tale sovraccarico.
Se vuoi anche assicurarti una lunghezza minima , potresti riempirla prima con qualcosa del tipo:
pax> long="A"
pax> tmpstr="${long}.."
pax> short="${tmpstr:0:2}" ; echo "${short}"
A.
Ciò garantirebbe che qualsiasi cosa di lunghezza inferiore a due caratteri fosse riempita sulla destra con punti (o qualcos'altro, semplicemente cambiando il carattere usato durante la creazione tmpstr
). Non è chiaro se ne hai bisogno, ma ho pensato di inserirlo per completezza.
Detto questo, ci sono molti modi per farlo con programmi esterni (ad esempio se non hai a bash
disposizione), alcuni dei quali sono:
short=$(echo "${long}" | cut -c1-2)
short=$(echo "${long}" | head -c2)
short=$(echo "${long}" | awk '{print substr ($0, 0, 2)}'
short=$(echo "${long}" | sed 's/^\(..\).*/\1/')
I primi due ( cut
e head
) sono identici per una stringa a riga singola: fondamentalmente entrambi restituiscono solo i primi due caratteri. Si differenziano per il fatto che cut
ti daranno i primi due caratteri di ogni riga e head
ti daranno i primi due caratteri dell'intero input
Il terzo utilizza la funzione di awk
sottostringa per estrarre i primi due caratteri e il quarto utilizza i sed
gruppi di acquisizione (utilizzando ()
e \1
) per acquisire i primi due caratteri e sostituire l'intera riga con essi. Sono entrambi simili a cut
: forniscono i primi due caratteri di ogni riga nell'input.
Niente di tutto ciò ha importanza se sei sicuro che il tuo input sia una singola riga, hanno tutti lo stesso effetto.
printf '%s'
invece di echo
nel caso in cui ci siano caratteri strani nella stringa: stackoverflow.com/a/40423558/895245 Per l'ossessione POSIX: head -c
non è POSIX cut -c
e non lo awk substr
sono, sed \1
non sono sicuro.
il modo più semplice è
${string:position:length}
Dove questo estrae la $length
sottostringa da $string
a $position
.
Questo è un builtin bash quindi awk o sed non è richiesto.
Hai ottenuto più risposte buone e mi piacerebbe andare con la Bash incorporato me stesso, ma dal momento che hai chiesto sed
e awk
e ( quasi ) nessun altro offerto soluzioni basate su di essi, vi questi offrono:
echo "USCAGoleta9311734.5021-120.1287855805" | awk '{print substr($0,0,2)}'
e
echo "USCAGoleta9311734.5021-120.1287855805" | sed 's/\(^..\).*/\1/'
La awk
si dovrebbe essere abbastanza ovvio, ma qui è una spiegazione del sed
uno:
substr($0,1,2)
.
Se sei dentro bash
, puoi dire:
bash-3.2$ var=abcd
bash-3.2$ echo ${var:0:2}
ab
Questo potrebbe essere proprio quello di cui hai bisogno ...
Solo grep:
echo 'abcdef' | grep -Po "^.." # ab
-P
opzione per renderlo più breve. Tutte le espressioni regolari capiranno quel modello.
Puoi usare printf
:
$ original='USCAGoleta9311734.5021-120.1287855805'
$ printf '%-.2s' "$original"
US
Abbastanza tardi in effetti, ma eccolo qui
sed 's/.//3g'
O
awk NF=1 FPAT=..
O
perl -pe '$_=unpack a2'
Se vuoi usare lo scripting della shell e non fare affidamento su estensioni non posix (come i cosiddetti bashismi), puoi usare tecniche che non richiedono strumenti esterni di fork come grep, sed, cut, awk, ecc., Che poi rendere il tuo script meno efficiente. Forse l'efficienza e la portabilità posix non sono importanti nel tuo caso d'uso. Ma nel caso lo sia (o semplicemente come una buona abitudine), puoi usare il seguente metodo di opzione di espansione dei parametri per estrarre i primi due caratteri di una variabile di shell:
$ sh -c 'var=abcde; echo "${var%${var#??}}"'
ab
Utilizza l' espansione del parametro "prefisso più piccolo" per rimuovere i primi due caratteri (questa è la ${var#??}
parte), quindi l' espansione del parametro "suffisso più piccolo" (la ${var%
parte) per rimuovere la stringa di tutti i caratteri tranne i primi due dall'originale valore.
Questo metodo è stato precedentemente descritto in questa risposta alla domanda "Shell = Controlla se la variabile inizia con #". La risposta descrive anche un paio di metodi di espansione dei parametri simili che possono essere utilizzati in un contesto leggermente diverso da quello che si applica alla domanda originale qui.
Se il tuo sistema utilizza una shell diversa (non bash
), ma il tuo sistema lo ha bash
, puoi comunque utilizzare la manipolazione intrinseca delle stringhe bash
invocando bash
con una variabile:
strEcho='echo ${str:0:2}' # '${str:2}' if you want to skip the first two characters and keep the rest
bash -c "str=\"$strFull\";$strEcho;"
bash
se non lo stai già utilizzando.
Solo per divertimento, ne aggiungerò alcune che, sebbene siano troppo complicate e inutili, non sono state menzionate:
head -c 2 <( echo 'USCAGoleta9311734.5021-120.1287855805')
echo 'USCAGoleta9311734.5021-120.1287855805' | dd bs=2 count=1 status=none
sed -e 's/^\(.\{2\}\).*/\1/;' <( echo 'USCAGoleta9311734.5021-120.1287855805')
cut -c 1-2 <( echo 'USCAGoleta9311734.5021-120.1287855805')
python -c "print(r'USCAGoleta9311734.5021-120.1287855805'[0:2])"
ruby -e 'puts "USCAGoleta9311734.5021-120.1287855805"[0..1]'
se mystring = USCAGoleta9311734.5021-120.1287855805
print substr(mystring,0,2)
ci stamperebbe
dove 0 è la posizione iniziale e 2 è il modo in cui leggere i caratteri
awk
. Scusa, all'inizio non potevo dirlo.
È questo quello che cerchi?
my $string = 'USCAGoleta9311734.5021-120.1287855805';
my $first_two_chars = substr $string, 0, 2;
rif: substr
perl -e 'print substr $ARGV[0], 0, 2' 'USCAGoleta9311734.5021-120.1287855805'