command grep pour afficher toutes les lignes qui commencent et se terminent avec 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.

    POSIXly:

     pattern='\(.\).*\1 .' grep -x -- "$pattern" file 

    Cela ne fonctionnera pas si la ligne commence ou se termine par un caractère d'octet invalide. Si vous voulez couvrir ce cas, vous pouvez append LC_ALL=C , bien que LC_ALL=C fonctionne qu'avec des données de caractères sur un seul octet.


    perl6 semble être le meilleur outil, si vous l'avez dans votre boite:

     $ printf '\ue7\u301 blah \u107\u327\n121\n1\n123\n' | perl6 -ne '.say if m/^(.).*$0$/ || /^.$/' ḉ blah ḉ 121 1 

    Bien qu'il s'étouffe encore sur les caractères invalides.


    Notez que perl6 va modifier votre text en le convertissant en formulaire NFC :

     $ 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 string sous forme NFG (stand for Normalization Form Grapheme ), qui est perl6 inventé façon 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 

    Pas grep mais awk:

     awk -F "" 'NF && $1 == $NF' 

    Ces cas spéciaux sont traités:

    • il n'imprime pas les lignes vides
    • il imprime toujours des lignes de 1 caractère

    Un FS vide divise l'logging en un seul caractère par 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ée de l'original par A , W et K comme sur les BSD et les Unices commerciaux. Plus portable mais plus à taper:

     awk '/./ && substr($0,1,1) == substr($0,length)' 
     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 reference arrière au caractère capturé dans \(.\) . Nous ajoutons un -e . pour prendre soin du cas particulier d'une ligne contenant un seul caractère.

    Il suppose que l'input contient du text valide dans les parameters régionaux en cours.

    La correspondance est sur le caractère et non sur l' octet (les é en UTF-8 sont les deux octets 0xc3 0xa9 par exemple), ni grappe graphem (cela ne marcherait pas si ces é étaient écrits dans leur forme décomposée avec e suivi de U + 0301 combinant un accent aigu par exemple).

    Pour travailler sur les grappes de graphes, avec un grep qui supporte -P pour 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 à celui exprimé par c U+0327 U+0301 ou ć ( U+0107 ) U+0327 ou ç ( U+00E7 ) U+0301 ou ḉ ( U+1E09 ). Pour cela, vous devez faire le contrôle sur un formulaire normalisé:

     $ printf '\ue7\u301 blah \u107\u327\n' | perl -MUnicode::Normalize -C -ne ' print if /^\X$/ || NFC($_) =~ /^(\X).*\1$/' ḉ blah ḉ 

    Alternative rapide à python2:

     python -c 'import sys;[sys.stdout.write(l) for l in sys.stdin if len(l)>1 and l.rssortingp("\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.rssortingp("\n").endswith(l[0])]' < input.txt | cat -A nathan$ ookie $ a line a$