Как мне посчитать слова в части файла, не покидая vim?

10

У меня есть файл, полный текста (скажем, Markdown или LaTeX). Я хотел бы посчитать количество слов в части этого файла.

Я знаю, что могу сделать :! wc -w %для запуска wc -w на текущий буфер. И я знаю, что могу вставить интересующий раздел в именованный регистр. Я предполагаю, что есть способ отправить именованный регистр в операционную систему для использования в команде или канале, но я не смог его найти. Или есть лучший способ считать слова в регистре?

Мой пример использования заключается в том, что я много пишу без программирования (заметки, тезисы и т. Д.) В vim, и я хотел бы посчитать, сколько слов я добавил в данный раздел файла в середине редактирования сессия.

Колин Макфол
источник

Ответы:

16

Вы можете использовать gCTRL+g, который даст вам:

Col 1 of 118-121; Line 1 of 5; Word 1 of 142; Byte 1 of 678

Вы также можете использовать это из визуального режима, если вы хотите получить количество слов только для выделения, что особенно полезно в сочетании с текстовыми объектами, такими как ip. (например, вы можете использовать, vipg<C-g>чтобы получить количество слов текущего абзаца).

Смотрите: :help word-countа :help text-objects.


Вышеупомянутая опция, вероятно, лучше, но вы также можете использовать wcутилиту для подсчета количества слов в разделе. Помимо :! wc -w %формы, которую вы используете, вы также можете использовать :%!wc -w. Это отфильтрует движение к инструменту оболочки (в данном случае %ко всему буферу), но вы также можете использовать другие диапазоны (например, :1,5!wc -wдля первых 5 строк, !,+5!wc -wдля текущей и следующих 5 строк и т. Д.). Вы также можете выбрать текст в визуальном режиме и набрать, :!wc -wчтобы отфильтровать ваш выбор.

Обратите внимание, что это заменит движение выводом инструмента оболочки, но вы можете uотменить это.

Видите :help :range!, :help rangeи этот ответ, где я привожу больше примеров диапазонов.

Мартин Турной
источник
Я нашел что-то подобное во время поиска, но пропустил, что первый g является частью команды подсчета, а не спецификатором местоположения. Это решение имеет смысл сейчас. Я, видимо, также должен читать в визуальном режиме; Я не использую это достаточно часто.
Колин Макфол
1
Я понятия не имел, что ты можешь использовать g<C-g>этот способ. Потрясающие!
EvergreenTree
3

Есть два способа, которыми это может быть достигнуто, чистый способ vimscript и wcспособ.

Чистый путь Vim

Вы можете использовать команду поиска и замены, чтобы сделать это. Например:

:%s/\<\w\{-}\>//gn

То, что это делает, вместо того, чтобы заменить данный шаблон чем-то, он просто считает вхождения шаблона. Это из-за nфлага. Чтобы подсчитать слова в определенном разделе (в данном случае строки с 5 по 15), вы можете сделать что-то вроде этого:

:5,15s/\<\w\{-}\>//gn

Это избавляет от необходимости вытягивать содержимое выбора в регистр. Чтобы увидеть больше возможностей для того, что можно поставить на место 5-15, прочитайте раздел справки для cmdline-ranges. Если вы хотите делать это часто, вероятно, лучше создать для него отображение (или команду). Кроме того, если вы hlsearchвключили, вы можете запустить :nohlsearchпозже, чтобы очистить выделение.

wcпуть

То же самое можно сделать с помощью wc. Таким же образом вы можете использовать cmdline-rangesдля выбора области с помощью :sкоманды, вы можете использовать их с внешними командами. Например:

:5,15!wc -w

Это запускает строки с 5 по 15 через wcкоманду. Недостатком этого является то, что он заменяет этот диапазон строк выходными данными команды. Вы можете отменить это изменение, нажав u. Также обратите внимание, что решение vimscript может не работать с разными языками, потому \wчто не соответствует тому, что обычно является символами слова в других языках. wcможет быть лучше, чем \w. Кроме того, вот необычная команда, чтобы сделать это быстрее:

command -range=% -addr=lines WordCount execute '<count>!wc -w' | .y a | undo | echo @a

Обратите внимание, что это забивает aрегистр.

Запись

Похоже, что это также может быть выполнено в визуальном режиме с g<C-g>комбинацией клавиш. См. Ответ Carpetsmoker для объяснения этого.

Вечнозеленое дерево
источник
Они должны быть вместе с n, чтобы сделать их глобальными (в противном случае они соответствуют только одному слову в строке). Второй также нуждается в s в начале.
Колин Макфол
1
Исправлено, извините за это.
EvergreenTree
1
Поначалу \wзвучит как хорошая идея, но после тестирования я обнаружил ряд проблем. Самое большое, что он не будет соответствовать не-ascii символам, поэтому слово like überпросто пропускается ( вчера был вопрос об этом ). Кроме того, слово like e-mailсчитается как 2 слова, так -как его нет \w(использование a -несколько необычно в английском языке, но, например, очень часто встречается в голландском). Могут быть и другие персонажи, которые игнорируются таким образом, что подводит нас к моему последнему пункту: соглашения о том, что считать «словом», могут отличаться ...
Мартин Турной,
... на разных языках, и "правильные" инструменты, такие как wcмогут появиться в локали (я не знаю, wcкстати, действительно ли GNU справляется с этим, инструменты GNU не очень хорошо известны благодаря своей превосходной поддержке юникода).
Мартин Турной
Это интересно. Я мог бы добавить это как плюс к wcрешению.
EvergreenTree
1

Для слов используйте:

:.,+4 s/\i\+/&/gn

. обозначает текущую строку.

Также я помещаю следующее в мой файл .vimrc:

:cabbrev zzcc   s/./&/gn

:cabbrev zzcw   s/\i\+/&/g

Я могу печатать:

:.,+6 zzcw

и zzcwрасширится доs/\i\+/&/g

Это zzcwпросто странное имя, которое не подходит ни для чего (для меня).

Побочным эффектом является выделение и выделение всего файла.

Я хотел иметь возможность вводить многострочные твиты в файл, следить за тем, чтобы их было не слишком много, и вставлять твиты в твиттер.

elademanon
источник