Je veux savoir comment utiliser greppour afficher toutes les lignes qui commencent et se terminent par le même caractère.
Je veux savoir comment utiliser greppour afficher toutes les lignes qui commencent et se terminent par le même caractère.
Réponses:
POSIX:
pattern='\(.\).*\1
.'
grep -x -- "$pattern" file
Cela ne fonctionnera pas si la ligne commence ou se termine avec un caractère d'octet non valide, si vous voulez couvrir ce cas, vous pouvez l'ajouter LC_ALL=C, bien que cela ne LC_ALL=Cfonctionne qu'avec des données de caractère à un seul octet.
perl6 semble être le meilleur outil, si vous l'avez dans votre boîte:
$ printf '\ue7\u301 blah \u107\u327\n121\n1\n123\n' |
perl6 -ne '.say if m/^(.).*$0$/ || /^.$/'
ḉ blah ḉ
121
1
Bien qu'il s'étouffe toujours avec des caractères invalides.
Notez que perl6cela modifiera votre texte en le transformant en NFCforme:
$ printf '\u0044\u0323\u0307\n' |
perl6 -pe '' |
perl -CI -ne 'printf "U+%04x\n", ord for split //'
U+1e0c
U+0307
U+000a
$ printf '\u0044\u0323\u0307\n' |
perl -pe '' |
perl -CI -ne 'printf "U+%04x\n", ord for split //'
U+0044
U+0323
U+0307
U+000a
En interne, perl6stocke la chaîne sous NFGforme (stand for Normalization Form Grapheme), qui est un perl6moyen inventé de traiter correctement les graphèmes non précomposés:
$ printf '\u0044\u0323\u0307\n' | perl6 -ne '.chars.say'
1
$ printf '\u0044\u0323\u0307\n' | perl6 -ne '.codes.say'
2
perl6cela modifiera le texte (le transformer en NFC (formulaire de normalisation "composé")).
perl6est stockée sous NFGforme ( Gpour Grapheme), ce qui est un perl6moyen de gérer correctement les graphèmes non pré-composés.
Pas grep mais awk:
awk -F "" 'NF && $1 == $NF'
Ces cas particuliers sont traités:
Un FS vide divise l'enregistrement en un caractère par champ dans gawk, mawket busybox awk(octets, pas des caractères pour les deux derniers), mais n'est pas standard et ne fonctionne pas dans les implémentations de awkdérivé de l'original par A, W et K comme sur les BSD et les Unités commerciales. Plus portable mais plus à taper:
awk '/./ && substr($0,1,1) == substr($0,length)'
FSchaîne vide n'est pas standard et ne fonctionnera pas dans certaines awkimplémentations.
awk 'length&&substr($0,1,1)==substr($0,length)'(notez l'argument par défaut de lengthis $0et l'action par défaut est {print $0})
nawkce qui est presque aussi mauvais :-)
grep -xe '\(.\).*\1' -e .
Exemple:
$ printf '%s\n' il y était cet été | grep -xe '\(.\).*\1' -e .
y
été
-xest pour une correspondance exacte (correspondance sur toute la ligne). \1étant une référence arrière au personnage capturé dans \(.\). Nous ajoutons un -e .pour prendre en charge le cas particulier d'une ligne contenant un seul caractère.
Il suppose que l'entrée contient du texte valide dans les paramètres régionaux actuels.
La correspondance est sur le caractère , pas sur l' octet (ceux é en UTF-8 sont les deux octets 0xc3 0xa9 par exemple), ni le graphe graphem (cela ne fonctionnerait pas si ceux é étaient écrits sous leur forme décomposée avec esuivi du U + 0301 combinant un accent aigu par exemple).
Pour travailler sur des grappes graphem, avec un grepqui prend en charge -PPCRE:
$ printf 'e\u0301te\u0301\n' | grep -xPe '(\X).*\1|\X'
été
Cela suppose que la décomposition est la même pour les deux grappes, par exemple un ḉexprimé comme c U+0301 U+0327ne correspondrait pas à un exprimé comme c U+0327 U+0301ou ć( U+0107) U+0327ou ç( U+00E7) U+0301ou ḉ ( U+1E09). Pour cela, vous devez effectuer la vérification sur un formulaire normalisé:
$ printf '\ue7\u301 blah \u107\u327\n' |
perl -MUnicode::Normalize -C -ne '
print if /^\X$/ || NFC($_) =~ /^(\X).*\1$/'
ḉ blah ḉ
perl6, alors perl6 -ne '.say if m/^(.).*$0$/ || /^.$/'faites tout le travail pour vous.
Alternative rapide à python2:
python -c 'import sys;[sys.stdout.write(l) for l in sys.stdin if len(l)>1 and l.rstrip("\n").endswith(l[0])]' < input.txt
Exemple:
$ python -c 'import sys;[sys.stdout.write(l) for l in sys.stdin if len(l)>1 and l.rstrip("\n").endswith(l[0])]' < input.txt | cat -A
nathan$
ookie $
a line a$