Comment extraire les deux premiers caractères d’une chaîne dans le script shell?

Par exemple, donné:

USCAGoleta9311734.5021-120.1287855805 

Je veux juste extraire:

 US 

Probablement la méthode la plus efficace, si vous utilisez le shell bash (et vous semblez l’être, selon vos commentaires), est d’utiliser la variante de sous-chaîne de l’extension de paramètre:

 pax> long="USCAGol.blah.blah.blah" pax> short="${long:0:2}" ; echo "${short}" US 

Ce sera short pour être les deux premiers caractères de long . Si long est plus court que deux caractères, le short sera identique.

Cette méthode interne est généralement meilleure si vous voulez le faire beaucoup (comme 50 000 fois par rapport, comme vous le mentionnez), car il n’y a pas de surcharge de création de processus. Toutes les solutions utilisant des programmes externes souffriront de cette surcharge.

Si vous vouliez également vous assurer une longueur minimale , vous pourriez la mettre à disposition avec quelque chose comme:

 pax> long="A" pax> tmpstr="${long}.." pax> short="${tmpstr:0:2}" ; echo "${short}" A. 

Cela garantirait que tout ce qui a moins de deux caractères de longueur soit complété à droite par des points (ou autre chose, simplement en changeant le caractère utilisé lors de la création de tmpstr ). Il n’est pas clair que vous en ayez besoin mais je pensais que je le mettrais pour être complet.


Cela étant dit, il existe plusieurs moyens de le faire avec des programmes externes (comme si vous n’aviez pas de bash à votre disposition), dont certains 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 and head ) sont identiques pour une chaîne à une seule ligne – ils vous renvoient simplement les deux premiers caractères. Ils diffèrent dans cette cut vous donnera les deux premiers caractères de chaque ligne et la head vous donnera les deux premiers caractères de l’entrée entière

Le troisième utilise la fonction de sous-chaîne awk pour extraire les deux premiers caractères et le quasortingème utilise les groupes de capture sed (using () et \1 ) pour capturer les deux premiers caractères et remplacer la ligne entière par ces derniers. Ils sont tous les deux similaires à cut – ils fournissent les deux premiers caractères de chaque ligne dans l’entrée.

Rien de tout cela n’est important si vous êtes certain que votre entrée est une seule ligne, elles ont toutes un effet identique.

le plus simple est

 ${ssortingng:position:length} 

Où cela extrait la sous-chaîne $length de $ssortingng à $position .

Ceci est une bash builtin, donc awk ou sed n’est pas requirejs.

Vous avez eu 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 eux, je vous les offre:

 echo "USCAGoleta9311734.5021-120.1287855805" | awk '{print substr($0,0,2)}' 

et

 echo "USCAGoleta9311734.5021-120.1287855805" | sed 's/\(^..\).*/\1/' 

Le awk one devrait être assez évident, mais voici une explication du sed :

  • remplacer “s /”
  • le groupe “()” de deux caractères quelconques “..” commençant au début de la ligne “^” et suivi de tout caractère “.” répété zéro ou plusieurs fois “*” (les barres obliques inverses sont nécessaires pour échapper à certains caractères spéciaux)
  • par “/” le contenu du premier groupe (et seulement dans ce cas) (ici la barre oblique inverse est une échappée spéciale faisant référence à une sous-expression correspondante)
  • terminé “/”

Si vous êtes en bash , vous pouvez dire:

 bash-3.2$ var=abcd bash-3.2$ echo ${var:0:2} ab 

Cela peut être juste ce dont vous avez besoin…

Juste grep:

 echo 'abcdef' | grep -Po "^.." # ab 

Assez tard en effet mais la voici

 sed 's/.//3g' 

Ou

 awk NF=1 FPAT=.. 

Ou

 perl -pe '$_=unpack a2' 

colrm – supprime les colonnes d’un fichier

Pour laisser les deux premiers caractères, il suffit de supprimer les colonnes à partir de 3

 cat file | colrm 3 

Si votre système utilise un shell différent (pas bash ), mais que votre système a 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;" 

Si vous souhaitez utiliser les scripts shell et ne pas vous fier aux extensions non-posix (telles que les soi-disant bashismes), vous pouvez utiliser des techniques qui ne nécessitent pas l’utilisation d’outils externes tels que grep, sed, cut, awk, etc. rendre votre script moins efficace. L’efficacité et la portabilité des posix ne sont peut-être pas importantes dans votre cas d’utilisation. Mais si c’est le cas (ou juste comme une bonne habitude), vous pouvez utiliser la méthode 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’ extension de paramètre “plus petit préfixe” pour supprimer les deux premiers caractères (il s’agit de la partie ${var#??} ), puis l’ extension de paramètre “plus petit suffixe” (la partie ${var% ) pour supprimer ce tout-sauf. la chaîne des deux premiers caractères de la valeur d’origine.

Cette méthode a été décrite précédemment dans cette réponse à la question “Shell = Vérifier si la variable commence par #”. Cette réponse décrit également deux méthodes d’extension de parameters similaires pouvant être utilisées dans un contexte légèrement différent de celui de la question initiale.

 perl -ple 's/^(..).*/$1/' 

si myssortingng = USCAGoleta9311734.5021-120.1287855805

 print substr(myssortingng,0,2) 

imprimerait US

où 0 est la position de départ et 2 est la façon dont les caractères doivent être lus

Est-ce que c’est votre après?

 my $ssortingng = 'USCAGoleta9311734.5021-120.1287855805'; my $first_two_chars = substr $ssortingng, 0, 2; 

ref: substr