У меня есть файл, содержание которого похоже на следующий.
0
0
0.2
0
0
0
0
Мне нужно удалить все строки с одним нулем.
Я думал использовать grep -v "0"
, но это удаляет также строку, содержащую 0,2. Я видел, что могу использовать эту -w
опцию, но это тоже не работает.
Как я могу удалить все строки, содержащие только один 0, и сохранить все эти строки, начиная с 0?
-w
, что здесь не так.grep
для этой задачи? А что именно вы подразумеваете под одним нулем ? Это очень похоже на проблему XY .Ответы:
От
man grep
:-w
терпит неудачу, потому что первый0
в0.02
считается "словом", и, следовательно, эта строка соответствует. Это потому, что за ним следует символ «не слово». Вы можете увидеть это , если вы запустите оригинальную команду без-v
, то естьgrep -w "0"
.источник
-F
опцию, так как мы не используем шаблоны регулярных выражений, просто сопоставление строк-F
(на удивление для меня), кажется, занимает такое же количество времени или даже немного медленнее (~ 5–10%). Следовательно, я не уверен, какое преимущество будет.grep
предположительно, есть специальный случай для регулярных выражений без метасимволов, потому что это распространенный вариант использования. Удивительно, чтоfgrep
это будет медленнее, но не удивительно, что издержки, связанные с замечанием этого особого случая при составлении короткого шаблона, незначительны по сравнению со временем сканирования большого файла. (Если для такой скорости требуется особый случай, а не шаблон с классом персонажей илиx.*y
.)grep
распознает какой-либо символ, кроме\n
новой строки, в качестве разделителя строк. Если нет, то неявный^
и$
все еще может превратиться в поиск с фиксированной строкой, какstrstr(big_buf, "\n0\n")
. (Или0\n
в начале буфера.) Но мы не просто ищем первое совпадение, потенциально находящееся далеко в большом буфере, мы хотим эффективно фильтровать. Но в любом случае, теоретически да, это просто 2-байтовый memcmp в начале каждой строки, и вы надеетесь, что и fgrep, и grep это увидят.С grep:
^
означает начало строки,$
означает конец строки.источник
[a-Z0-9]
Хотя это
grep
может быть использовано для этого (как ясно показывают другие ответы), давайте сделаем шаг назад и подумаем о том, что вы на самом деле хотите:Regex интерпретирует данные последовательности символов. Они не знают о числах, только об отдельных цифрах (и их регулярных комбинациях). Хотя в вашем конкретном случае есть простое решение этого ограничения, в конечном итоге это несоответствие требований.
Если нет очень веской причины для использования
grep
здесь (например, потому что вы измерили его, и он намного более эффективен, а эффективность в вашем случае имеет решающее значение), я рекомендую использовать другой инструмент.awk
Например, может фильтровать на основе числовых сравнений, например:Но также, чтобы получить все строки, содержащие числа больше нуля:
Я люблю регулярные выражения, это отличный инструмент. Но это не единственный инструмент. Как говорится, если все, что у вас есть
grep
, все выглядит как обычный язык.источник
printf '0\n1\n-1\na\nb\n0\n0 also\n0.0\n-0.0\n0*0\n' | awk '($1 == 0)'
будет соответствовать:0
,0.0
а-0.0
... а также0 also
! Не просто "0". (что иногда то, что нужно, иногда нет). Если пользователь хочет только «0»:awk '/^0$/'
(илиgrep '^0$'
). Также вам следует отредактировать: пользователю нужно добавить,!
чтобы отменить тест, чтобы он скрывал0
(и другие нули) и отображал остальное.awk '!( $0 == 0)'
$1 == "0"
>
а не!=
(или, что то же самое! (… == …)
), чтобы подчеркнуть, что это произвольное числовое сравнение, а не просто равенство. Что касается вашего другого комментария, это полностью верно, но тогда мы по существу вернулись на территорию сравнения строк и существующее решение, использующееgrep
работы (хотя,awk
конечно, также работает).$0=="0"
grep
«s-w
немного запутанным таким образом , что она распадается на исходную строку в слова и не слова составляющих (ничего , кроме букв, цифр или подчеркивания). Поскольку он уже столкнулся с действительным составным словом,0
в0.02
нем утверждена логика отрицания для удаления строки.Использование
sed
в этом контексте немного просто, чтобы просто удалить все слова, которые соответствуютисточник
Когда строки , которые вы хотите удалить только содержать
0
затем в следующей строке вы можете выбрать те строки, выполнив следующую команду:Это напечатает только вхождения,
0
которые находятся в конце строки и в начале строки одновременно.-v
Опция инвертирует наш выбор.источник
-v
, поэтому он не работает.-v
опцией, спасибо!grep -v "\b0\b"
grep -v "^0$"
-w работает, но в вашем случае 0.2 два слова, потому что символ точки является разделителем слов.
источник
grep -v "\b0\b"
на самом деле не работает здесь. Какую версию grep вы используете?grep (BSD grep) 2.5.1-FreeBSD
MacOS иgrep (GNU grep) 2.16
Ubuntu\<
и в\>
качестве границ слов, но это будет иметь тот же эффект, что и-w
Еще один ответ ради разнообразия, если у вас есть PCRE-включен
grep
это выполняет отрицательный прогноз, чтобы соответствовать линиям, которые начинаются с
0
и не сопровождаются точкой. Затем-v
отбрасывает несовпадающие строки. Вы можете увидеть в действии здесьисточник
0123
, что не то, что хочет ОППредполагая, что любая строка, которая не является просто 0, имеет точку
grep '\.' file
источник