Je veux savoir comment utiliser grep
pour afficher toutes les lignes qui commencent et se terminent par le même caractère.
Je veux savoir comment utiliser grep
pour 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=C
fonctionne 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 perl6
cela modifiera votre texte en le transformant en NFC
forme:
$ 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, perl6
stocke la chaîne sous NFG
forme (stand for Normalization Form Grapheme
), qui est un perl6
moyen 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
perl6
cela modifiera le texte (le transformer en NFC (formulaire de normalisation "composé")).
perl6
est stockée sous NFG
forme ( G
pour Grapheme
), ce qui est un perl6
moyen 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
, mawk
et 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 awk
dé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)'
FS
chaîne vide n'est pas standard et ne fonctionnera pas dans certaines awk
implémentations.
awk 'length&&substr($0,1,1)==substr($0,length)'
(notez l'argument par défaut de length
is $0
et l'action par défaut est {print $0}
)
nawk
ce qui est presque aussi mauvais :-)
grep -xe '\(.\).*\1' -e .
Exemple:
$ printf '%s\n' il y était cet été | grep -xe '\(.\).*\1' -e .
y
été
-x
est 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 e
suivi du U + 0301 combinant un accent aigu par exemple).
Pour travailler sur des grappes graphem, avec un grep
qui prend en charge -P
PCRE:
$ 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+0327
ne correspondrait pas à un exprimé comme c
U+0327
U+0301
ou ć
( U+0107
) U+0327
ou ç
( U+00E7
) U+0301
ou ḉ ( 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$