Par exemple, étant donné:
USCAGoleta9311734.5021-120.1287855805
Je souhaite extraire uniquement:
US
Par exemple, étant donné:
USCAGoleta9311734.5021-120.1287855805
Je souhaite extraire uniquement:
US
Réponses:
La méthode probablement la plus efficace, si vous utilisez le bash
shell (et que vous semblez l'être, d'après vos commentaires), est d'utiliser la variante de sous-chaîne de l'expansion des paramètres:
pax> long="USCAGol.blah.blah.blah"
pax> short="${long:0:2}" ; echo "${short}"
US
Il s'agira short
des deux premiers caractères de long
. Si long
est plus court que deux caractères,short
sera identique.
Cette méthode en shell est généralement meilleure si vous comptez le faire beaucoup (comme 50000 fois par rapport, comme vous le mentionnez) car il n'y a pas de surcharge de création de processus. Toutes les solutions qui utilisent des programmes externes souffriront de cette surcharge.
Si vous souhaitez également garantir une longueur minimale , vous pouvez le compléter au préalable avec quelque chose comme:
pax> long="A"
pax> tmpstr="${long}.."
pax> short="${tmpstr:0:2}" ; echo "${short}"
A.
Cela garantirait que tout élément de moins de deux caractères de longueur soit complété à droite avec des points (ou autre chose, simplement en changeant le caractère utilisé lors de la création tmpstr
). Il n'est pas clair que vous en ayez besoin, mais j'ai pensé que je le mettrais pour être complet.
Cela dit, il existe un certain nombre de façons de le faire avec des programmes externes (par exemple si vous n'en avez pas bash
à votre disposition), dont certaines sont:
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/')
Les deux premiers ( cut
et head
) sont identiques pour une chaîne sur une seule ligne - ils ne vous renvoient que les deux premiers caractères. Ils diffèrent en ce que cut
vous donnera les deux premiers caractères de chaque ligne ethead
vous donnera les deux premiers caractères de toute l'entrée
Le troisième utilise la fonction de awk
sous-chaîne pour extraire les deux premiers caractères et le quatrième utilise des sed
groupes de capture (en utilisant ()
et \1
) pour capturer les deux premiers caractères et remplacer la ligne entière par eux. Ils sont tous deux similaires à cut
- ils fournissent les deux premiers caractères de chaque ligne dans l'entrée.
Rien de tout cela n'a d'importance si vous êtes sûr que votre entrée est une seule ligne, ils ont tous un effet identique.
printf '%s'
au echo
cas où il y aurait des caractères étranges dans la chaîne: stackoverflow.com/a/40423558/895245 Pour les obsédés de POSIX: head -c
n'est pas POSIX, cut -c
et ne awk substr
sont sed \1
pas sûrs.
Le moyen le plus simple est
${string:position:length}
Où cela extrait la $length
sous-chaîne à partir $string
de $position
.
C'est un bash intégré, donc awk ou sed n'est pas nécessaire.
Vous avez obtenu plusieurs bonnes réponses et j'irais avec le Bash intégré moi-même, mais depuis que vous avez posé des questions sur sed
et awk
et ( presque ) personne d'autre n'a proposé de solutions basées sur elles, je vous propose celles-ci:
echo "USCAGoleta9311734.5021-120.1287855805" | awk '{print substr($0,0,2)}'
et
echo "USCAGoleta9311734.5021-120.1287855805" | sed 's/\(^..\).*/\1/'
L' awk
un devrait être assez évident, mais voici une explication de l' sed
un:
substr($0,1,2)
.
Si vous êtes bash
, vous pouvez dire:
bash-3.2$ var=abcd
bash-3.2$ echo ${var:0:2}
ab
C'est peut-être exactement ce dont vous avez besoin…
Juste grep:
echo 'abcdef' | grep -Po "^.." # ab
-P
option pour la raccourcir. Toutes les expressions régulières comprendront ce modèle.
Vous pouvez utiliser printf
:
$ original='USCAGoleta9311734.5021-120.1287855805'
$ printf '%-.2s' "$original"
US
Assez tard en effet mais la voici
sed 's/.//3g'
Ou
awk NF=1 FPAT=..
Ou
perl -pe '$_=unpack a2'
Si vous souhaitez utiliser des scripts shell et ne pas compter sur des extensions non-posix (telles que les soi-disant bashismes), vous pouvez utiliser des techniques qui ne nécessitent pas de forger des outils externes tels que grep, sed, cut, awk, etc., qui alors rendre votre script moins efficace. Peut-être que l'efficacité et la portabilité posix ne sont pas importantes dans votre cas d'utilisation. Mais dans le cas où c'est le cas (ou juste comme une bonne habitude), vous pouvez utiliser la méthode d'option d' extension de paramètre suivante pour extraire les deux premiers caractères d'une variable shell:
$ sh -c 'var=abcde; echo "${var%${var#??}}"'
ab
Cela utilise l' expansion des paramètres "plus petit préfixe" pour supprimer les deux premiers caractères (c'est la ${var#??}
partie), puis l' expansion des paramètres "plus petit suffixe" (le${var%
partie) pour supprimer cette chaîne de caractères tout sauf les deux premiers de l'original valeur.
Cette méthode a été précédemment décrite dans cette réponse à la question "Shell = Vérifier si la variable commence par #". Cette réponse décrit également quelques méthodes d'expansion de paramètres similaires qui peuvent être utilisées dans un contexte légèrement différent de celui qui s'applique à la question d'origine ici.
Si votre système utilise un shell différent (pas bash
), mais que votre système l'a fait bash
, vous pouvez toujours utiliser la manipulation de chaîne inhérente de bash
en appelant bash
avec une variable:
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
si vous ne l'utilisez pas déjà.
Juste pour le plaisir, j'ajouterai quelques-uns qui, bien qu'ils soient trop compliqués et inutiles, n'ont pas été mentionnés:
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]'
si mystring = USCAGoleta9311734.5021-120.1287855805
print substr(mystring,0,2)
nous imprimerions
où 0 est la position de départ et 2 est comment lire les caractères meny
awk
. Désolé, je n'ai pas pu le dire au début.
C'est ce que vous recherchez?
my $string = 'USCAGoleta9311734.5021-120.1287855805';
my $first_two_chars = substr $string, 0, 2;
ref: substr
perl -e 'print substr $ARGV[0], 0, 2' 'USCAGoleta9311734.5021-120.1287855805'