Как я могу найти не-ASCII символы в текстовых файлах?

10512
Marcus Leon

Существует ли инструмент, который может сканировать небольшой текстовый файл и искать любые символы, не входящие в простой набор символов ASCII?

Простой Java или Groovy-скрипт также подойдет.

5
Он может быть перенесен туда, хотя может показаться, что это будет представлять непосредственный интерес для программистов в процессе выполнения определенных задач программирования .. (например, где я сейчас нахожусь) Marcus Leon 13 лет назад 0
Это не вопрос программирования, и поэтому он не по теме. Вы были здесь достаточно долго, чтобы знать это, но если нет, пожалуйста, прочитайте [FAQ] (http://stackoverflow.com/faq) для получения информации о том, какие вопросы обсуждаются здесь. :) Ken White 13 лет назад 0
Конечно, вы можете использовать `grep` с классом отрицанных символов. Tom Zych 13 лет назад 0
Все, что не пойдет по пути `grep '[^ \ x00- \ xFF]'` или его морального эквивалента ** с использованием существующих инструментов, не пишущих новую программу **, является просто безумным излишним. tchrist 13 лет назад 0
@ tchrist, хорошая мысль. Хотя у меня проблема с этим - http://stackoverflow.com/questions/7258299/grep-regex-doesnt-work-with-cygwin-on-windows Marcus Leon 13 лет назад 0
Используйте `grep -P '[^ \ x00- \ xFF]'` или `perl -ne 'print, если / [^ \ x00- \ xFF] /'`. Обратите внимание, что опция `-P` в grep на самом деле не принимает настоящие регулярные выражения Perl. tchrist 13 лет назад 0
@tchrist: ASCII не работает с 00 до 7F? Tom Zych 13 лет назад 0
@ Том: Да. Я просто подражал тому, что сделал ОП, что, как я поздно понял, не имело смысла. tchrist 13 лет назад 0

5 ответов на вопрос

2
Tom Zych

Ну, это все еще здесь через час, так что я могу также ответить на него. Вот простой фильтр, который печатает только входные символы, не входящие в ASCII, и выдает код выхода 0, если их не было, и 1, если они были. Читает только со стандартного ввода.

#include <stdio.h> #include <ctype.h>  int main(void) { int c, flag = 0;  while ((c = getchar()) != EOF) if (!isascii(c)) { putchar(c); flag = 1; }  return flag; } 
Спасибо, у вас есть Java-версия? :) Marcus Leon 13 лет назад 0
Нет, не делайте Java, извините. Tom Zych 13 лет назад 0
@Marcus: Монолингвизм примерно так же экологичен, как и любая другая монокультура. tchrist 13 лет назад 1
1
jonathan.cone

Просто запустите $ JDK_HOME / bin / native2ascii в текстовом файле и найдите «\ u» в выходном файле. Я предполагаю, что вы хотите найти это, чтобы вы могли избежать этого в любом случае, и это спасет вас на шаг. ;)

0
awfulHack

Я понятия не имею, допустимо ли это, приводя каждый символ к типу int и используя улов для определения неудачных вещей. Мне тоже лень писать это в Java, так что немного Groovy

def chars = ['Ã', 'a', 'Â', 'ç', 'x', 'o', 'Ð'];  chars.each{ try{ def asciiInt = (int) it } catch(Exception e){ print it + " "} } 

==> Ã Â ç Ð

0
Nathan Moos

В Java (при условии, что строка указана в качестве первого аргумента командной строки:

public class Main { public static void main(String[] args) { String stringToSearch = args[0]; int len = stringToSearch.length(); for (int i = 0; i < len; i++) { char ch = stringToSearch.charAt(i); if (ch >= 128) // non-ascii { System.out.print(ch + " "); } } System.out.println(); } } 

Чтобы сделать это самостоятельно, замените stringToSearchвсе, что вам нужно.

0
OverZealous

Простой заводной пример:

def str = [ "this doesn't have any unicode", "this one does ±ÁΘ·€ÔÅ" ]  str.each { if( it ==~ /[\x00-\x7F]*/ ) { println "all ascii: $it" } else { println "NOT ASCII: $it" } } 

Это так просто, как этот бит здесь: it ==~ /[\x00-\x7F]*/

Изменить: я забыл включить версию для файлов. К сожалению:

def text = new File(args[0]).text if( text ==~ /[\x00-\x7F]*/ ) { println "$ is only ASCII" System.exit(0) } else { println "$ contains non-ASCII characters" System.exit(-1) } 

Эта версия может использоваться в качестве сценария командной строки и включает состояние выхода, поэтому она может быть связана.

Нет смысла читать весь файл в память. Обратите внимание, что ** КАЖДАЯ ОДНА СТРОКА, КОГДА-ЛИБО СОЗДАННАЯ ** соответствует чему-то вроде `/ [\ x00- \ xFF] * /`, точно так же, как каждая отдельная строка также соответствует `/ a * /`, даже `" xxx "`. Ноль или более означает, что вы довольны 0. И `/ [\ x80- \ xFF] /` не ASCII! Вам нужно сопоставить `/ ^ [\ x00- \ x7F] + $ /`, чтобы быть всеми ASCII. Обычный движок регулярных выражений с самой базовой поддержкой Юникода просто использовал бы `\ p ` vs `\ P `. tchrist 13 лет назад 0
@ tchrist Я ценю обратную связь. Конечно, было бы более эффективно передавать файл. Тем не менее, оригинальный вопрос специально задан о сканировании ** маленького файла **. Ваш комментарий о регулярном выражении неверен, просто из-за того, что я действительно проверял свой код перед тем, как опубликовать его. Извините, если мой диапазон неверен - это может быть действительный комментарий, но ваш комментарий излишне агрессивен и груб. Я просто приводил работающий пример на Groovy, так как вопрос упоминал об этом. OverZealous 13 лет назад 0
Кроме того, вы должны соответствовать пустой строке, иначе пустые файлы будут отображаться как не-ASCII. Я думаю, что это неправильное поведение. OverZealous 13 лет назад 0
Нет, ASCII - это кодовые точки от 0 до 127. Ваш шаблон соответствует от 0 до 255. Поэтому он неверен. tchrist 13 лет назад 0
Я не должен был отвечать, но мне нужно указать на две вещи: во-первых, вы могли бы просто указать на это и предложить исправление, и я бы обновил свое предложение. Вот как работает StackExchange - ответы можно редактировать и очищать. Во-вторых, забавно, что вы так много делаете с диапазоном, поскольку это тот самый диапазон, который вы предложили выше! Это нормально, хотя, я понимаю, что вы бы лучше сбили кого-нибудь с ног, чем помогли бы. OverZealous 13 лет назад 0