Je sais que la cut
commande peut imprimer les premiers n
caractères d'une chaîne mais comment sélectionner les derniers n
caractères?
Si j'ai une chaîne avec un nombre variable de caractères, comment puis-je imprimer uniquement les trois derniers caractères de la chaîne. par exemple.
la sortie "illimitée" nécessaire est "ted" La sortie "987654" requise est "654" La sortie "123456789" requise est "789"
text-processing
cut
odyssée
la source
la source
grep -o '.\{3\}$'
echo "unlimited" | python -c "print raw_input()[-3:]"
"echo unlimited" | java -jar EnterpriseWordTrimmer.jar
, mais je ne pense pas qu'il soit vraiment nécessaire d'introduire un langage plus lourd pour la manipulation des personnages.java -server -Xms300M -Xmx3G -XX:+UseParallelGC -cp /path/to/all/the/jars/ -Dinput.interactive=false -Dinput.pipe=true -Dconfig.file=/path/to/config/last-three-letters.cfg -jar ...
grep -o -P '.{0,3}$'
imprime les 3 derniers caractères même si la ligne comporte moins de 3 caractères.-P
évite d'avoir à échapper aux accolades.Rester simple - queue
Nous ne devons pas avoir besoin d'une expression régulière, ni de plusieurs processus, juste pour compter les caractères.
La commande
tail
, souvent utilisée pour afficher les dernières lignes d'un fichier, a une option-c
(--bytes
), qui semble être juste le bon outil pour cela:(Lorsque vous êtes dans un shell, il est logique d'utiliser une méthode comme dans la réponse de mikeserv, car cela évite de démarrer le processus pour
tail
.)De vrais personnages Unicode?
Maintenant, vous demandez les trois derniers caractères ; Ce n'est pas ce que cette réponse vous donne: elle sort les trois derniers octets !
Tant que chaque caractère est un octet,
tail -c
ça fonctionne. Il peut donc être utilisé si le jeu de caractères estASCII
,ISO 8859-1
ou une variante.Si vous avez une entrée Unicode, comme dans le
UTF-8
format commun , le résultat est incorrect:Dans cet exemple, en utilisant
UTF-8
, les caractères grecs alpha, bêta et gamma ont une longueur de deux octets:L'option
-m
peut au moins compter les vrais caractères unicode:Ok, donc les 6 derniers octets nous donneront les 3 derniers caractères:
Donc,
tail
ne prend pas en charge la gestion des caractères généraux, et il n'essaie même pas (voir ci-dessous): il gère les lignes de taille variable, mais pas les caractères de taille variable.Disons-le de cette façon:
tail
est juste pour la structure du problème à résoudre, mais pas pour le type de données.GNU coreutils
Au -delà, il se trouve que Thee coreutils GNU, la collection d'outils de base comme
sed
,ls
,tail
etcut
, ne sont pas encore totalement internationalisé. Il s'agit principalement de prendre en charge Unicode.Par exemple,
cut
serait un bon candidat à utiliser au lieu de queue ici pour le support des personnages; Il a des options pour travailler sur les octets ou les caractères,-c
(--bytes
) et-m
(--chars
);Seul ce
-m
/--chars
n'est, à partir de la versioncut (GNU coreutils) 8.21
, 2013,pas implémenté!
De
info cut
:Voir aussi cette réponse à Vous ne pouvez pas utiliser `cut -c` (` --characters`) avec UTF-8? .
la source
cut
solution basée sur la vôtre et sur Glenn Jackman ne semble pas le faire.tail
doit traiter les octets et non les caractères. J'ai fait une fois un patch pour ajouter une nouvelle option pour sélectionner également des personnages, mais je pense que cela n'a jamais été fusionné: - /tail -c3 -n10 /var/log/syslog
tail -c3 -n10 /var/log/syslog
demande les 10 dernières lignes, et cela fonctionne pour moi. Vous utilisez l'option-c3
, puis l'option en conflit-n10
. La dernière option est prioritaire.Si votre texte est dans une variable shell appelée
STRING
, vous pouvez le faire dans unbash
,zsh
oumksh
shell:Ou
qui a également l'avantage de travailler avec ksh93 d'où vient cette syntaxe.
Le fait est que le
:
doit être séparé du-
, sinon il devient l'${var:-default}
opérateur du shell Bourne.La syntaxe équivalente dans les shells
zsh
ouyash
est:la source
${STRING:(-3):3}
(en spécifiant le champ de longueur ),${STRING: -3}
(avec un espace entre le:
et le-
), ou${STRING: -3:3}
.3
est quelque peu théorique car cela demande "les trois caractères du troisième au dernier caractère, inclus", ce qui s'avère être une opération identique en termes pratiques à "Tous les caractères à partir du troisième à partir du dernier" , inclusivement ".Utilisant
awk
:la source
Si la chaîne est dans une variable, vous pouvez faire:
Cela supprime les trois derniers caractères de la valeur de
$var
like:... puis se dépouille de la tête de
$var
tout, mais ce qui vient d'être dépouillé comme:Cette méthode a ses avantages et ses inconvénients. Du côté positif, il est entièrement portable POSIX et devrait fonctionner dans n'importe quelle coque moderne. De plus, si
$var
ne contient pas au moins trois caractères, rien d'autre que la ligne\n
ewline de fin n'est imprimé. Là encore, si vous souhaitez l'imprimer dans ce cas, vous avez besoin d'une étape supplémentaire comme:De cette façon, il
$last3
n'est jamais vide que s'il$var
contient 3 octets ou moins. Et$var
n'est jamais substitué à$last3
si$last3
est vide ouunset
- et nous savons que ce n'est pasunset
parce que nous venons de le définir.la source
printf
chaînes de format?${VARNAME:(-3)}
(en supposantbash
)?bash
que dans n'importe quel autre shell revendiquant la comapibilité POSIX.csh
est pas parmi les modernes, compatibles POSIX coquilles que je mentionne ici, malheureusement. La spécification POSIX-shell est modéliséeksh
, qui s'est modelée sur une combinaison des deuxcsh
et des coquilles traditionnelles de style Bourne.ksh
incorpore à la foiscsh
l'excellente fonctionnalité de contrôle des tâches et la redirection d'E / S des anciens styles Bourne. Il a également ajouté certaines choses - telles que les concepts de manipulation de chaînes que je démontre ci-dessus. Cela ne fonctionnera probablement pas dans n'importe quel traditionnelcsh
pour autant que je sache, je suis désolé de le dire.Vous pouvez le faire, mais c'est un peu ... excessif:
la source
La solution pare-balles pour les cordes utf-8:
Ou utiliser:
pour empêcher le traitement incorrect des données.
Exemple:
Produit quelque chose comme ceci:
Ne dépend pas des paramètres régionaux (c'est-à-dire fonctionne avec
LC_ALL=C
).Bash
,sed
,grep
,awk
,rev
Exiger quelque chose comme ceci:LC_ALL=en_US.UTF-8
Solution commune:
Vous pouvez détecter l'encodage avec uchardet . Voir également les projets associés .
Vous pouvez décoder / encoder avec Encode en Perl, les codecs en Python 2.7
Exemple :
Extraire les trois derniers caractères de la chaîne utf-16le et convertir ces caractères en utf-8
Voir aussi: perlunitut , Python 2 Unicode HOWTO
la source
echo
est votre source pare-balles?decode/encode
est ma source pare-balles. Nettoyé ma réponse.LC_ALL=C
car c'est un paramètre très "stupide", mais il peut se casser lorsque vous essayez de passer une chaîne UTF-8 à SHIFT-5, ou une chaîne SHIFT-5 à KOI8, etc.perl -CAO -e 'print substr($ARGV[0], -3)'
fonctionne bien.A
les éléments @ARGV devraient être des chaînes codées en UTF-8,O
STDOUT sera en UTF-8.utf8_str
Qu'en est-il de l'utilisation de "expr" ou "rev"?
Une réponse similaire à celle fournie par @ G-Man :
expr "$yourstring" : '.*\(...\)$'
elle présente le même inconvénient que la solution grep.Une astuce bien connue consiste à combiner "couper" avec "rev":
echo "$yourstring" | rev | cut -n 1-3 | rev
la source
rev
solution ressemble beaucoup à celle de Glenn JackmanObtenez la taille de la chaîne avec:
Ensuite, obtenez la sous-chaîne du dernier n caractère:
Par exemple:
donnerait:
la source
tail -n 1 revisions.log | awk '{print substr ($ 0, 0, longueur ($ 0) - (longueur ($ 0) -13))}'
Si vous souhaitez imprimer les treize premiers caractères du début
la source
printf ne fonctionnera pas si la chaîne contient des espaces.
Code ci-dessous pour la chaîne avec espace
la source
printf
ça ne marche pas, alors vous faites quelque chose de très mal.printf $str
(plutôt queprintf "$str"
ouprintf '%s' "$str"
). Et, oui,printf $str
c'est très faux. (ceecho -n $str
n'est pas beaucoup mieux.)