(grep) Regex pour correspondre aux caractères non ASCII?

169

Sous Linux, j'ai un répertoire avec beaucoup de fichiers. Certains d'entre eux ont des caractères non ASCII, mais ils sont tous UTF-8 valides . Un programme a un bogue qui l'empêche de fonctionner avec des noms de fichiers non ASCII, et je dois savoir combien sont affectés. J'allais faire cela avec find, puis faire un grep pour imprimer les caractères non ASCII, puis faire un wc -lpour trouver le nombre. Il n'est pas nécessaire que ce soit grep; Je peux utiliser n'importe quelle expression régulière Unix standard , comme Perl , sed , AWK , etc.

Cependant, existe-t-il une expression régulière pour «tout caractère qui n'est pas un caractère ASCII»?

Rory
la source
1
Paul, oui je peux utiliser perl
Rory
/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x9F]
Tinmarino

Réponses:

310

Cela correspondra à un seul caractère non ASCII:

[^\x00-\x7F]

Il s'agit d'un PCRE ( Expression régulière compatible Perl) valide .

Vous pouvez également utiliser les raccourcis POSIX :

  • [[:ascii:]] - correspond à un seul caractère ASCII
  • [^[:ascii:]] - correspond à un seul caractère non ASCII

[^[:print:]] vous suffira probablement. **

Alix Axel
la source
3
@adrianm: Non, ^est valide dans PCRE.
Alix Axel
10
C'est exactement ça. Cependant, vous devez utiliser pcregrep, pas grep standard. [^ [: print:]] ne fonctionnera pas si votre terminal est configuré en UTF8.
Rory
@Rory, pourquoi :print:ne fonctionnera pas dans un terminal UTF8? Cela fonctionne pour moi dans le levier dans un terminal UTF8:27.chr =~ /[^[:print:]]/
akostadinov
C'est vraiment bien pour corriger les mauvais noms de fichiers - rename 's/[^\x00-\x7F]//g' *(vous pouvez utiliser -npour vérifier que les renommages sont corrects en premier).
naught101
Comment faire correspondre un caractère non UTF8 et d'autres caractères spécifiques?
CMCDragonkai
37

Non, ce [^\x20-\x7E]n'est pas ASCII.

C'est du vrai ASCII:

 [^\x00-\x7F]

Sinon, il supprimera les nouvelles lignes et autres caractères spéciaux qui font partie de la table ASCII!

Peter L
la source
3

[^\x00-\x7F]et [^[:ascii:]]manquez quelques octets de contrôle afin que les chaînes soient parfois la meilleure option. Par exemple, cat test.torrent | perl -pe 's/[^[:ascii:]]+/\n/g'fera des choses bizarres sur votre terminal, où comme strings test.torrentse comportera.

user1133275
la source
3

Pour valider la zone de texte Accepter Ascii, utilisez uniquement ce modèle

[\x00-\x7F]+

Othman Mahmoud
la source
3

J'utilise [^\t\r\n\x20-\x7E]+et cela semble bien fonctionner.

SolidSnakeUk89
la source
2

Vous pouvez utiliser cette regex:

[^\w \xC0-\xFF]

Cas demandez, les options sont Multiline .

CypherPomme de terre
la source
2

Vous n'avez pas vraiment besoin d'une expression régulière.

printf "%s\n" *[!\ -~]*

Cela affichera également les noms de fichiers avec des caractères de contrôle dans leurs noms, mais je considère que c'est une fonctionnalité.

Si vous n'avez aucun fichier correspondant, le glob se développera uniquement sur lui-même, sauf si vous avez nullglobdéfini. (L'expression ne correspond pas à elle-même, donc techniquement, cette sortie est sans ambiguïté.)

tripleee
la source
Tardivement, je peux observer que cela ne fonctionnera correctement que si vous avez réellement des fichiers qui correspondent à ce modèle. Le comportement où le motif s'imprime lorsqu'il n'y a pas de correspondance est légèrement surprenant mais en fait correct. J'ai édité la réponse pour clarifier cela, espérons-le.
tripleee
1

Cela s'est avéré être très flexible et extensible. $ champ = ~ s / [^ \ x00- \ x7F] // g; # ainsi tous les éléments non ASCII ou spécifiques en question pourraient être nettoyés. Très agréable que ce soit dans la sélection ou le prétraitement des éléments qui finiront par devenir des clés de hachage.

Don Turnblade
la source