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 bashshell (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 shortdes deux premiers caractères de long. Si longest 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 ( cutet 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 cutvous 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 awksous-chaîne pour extraire les deux premiers caractères et le quatrième utilise des sedgroupes 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 echocas 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 -cn'est pas POSIX, cut -cet ne awk substrsont sed \1pas sûrs.
Le moyen le plus simple est
${string:position:length}
Où cela extrait la $lengthsous-chaîne à partir $stringde $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 sedet awket ( 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' awkun devrait être assez évident, mais voici une explication de l' sedun:
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
-Poption 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 bashen appelant bashavec 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;"
bashsi 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'