отключение eol, установка разделителей на перевод строки или перевод строки для включения токенизации по номерам строк - PullRequest
0 голосов
/ 24 октября 2018

Предисловие

  1. Я использую пакетную программу, чтобы сделать это
  2. , несмотря на множество «связанных» вопросов по этой теме, этот вопрос другой / не дубликат, потому что я хочутокенизировать строки, а не просто «читать построчно»

Что я делаю

Я хочу простой способ указать, какие строки я хочу проанализировать, и я подумал, что лучшедля этого нужно использовать опцию токенов цикла FOR.Проблема заключается в том, что токены по умолчанию разделяются по настройке eol (по умолчанию - перевод строки) и настройке delims (по умолчанию - пробел).Это отлично подходит для большинства случаев использования, но я хочу разбить каждую строку на токены.Это позволит мне делать то, что я хочу, легко и чисто.

Как я это пробовал

В любом случае, я понял, что вы можете отключить символ eol, выполнив eol ^ = в опциях FOR.Проблема в том, что я не могу найти фактический символ, который мне нужно указать в delims =, чтобы установить разделитель, равный новой строке, переводу строки или чему-либо еще, что обозначает только новую строку.Я не хочу просто обрабатывать строку за строкой, я хочу маркировать каждую строку.Это важно, потому что такие вопросы:

Новая строка в качестве разделителя цикла FOR

и это:

Какой разделитель использоватьв цикле FOR для чтения строк?

Не применяется.Кроме того, я нашел это, но ответы снова фактически не соответствовали моим потребностям.

https://www.dostips.com/forum/viewtopic.php?t=6471

Причина, по которой они не применяются, заключается в том, что те спрашивают о чтении файла построчно,Я спрашиваю о токенизации каждой строки.Это отличается тем, что построчное чтение можно выполнить, отключив delims и eol или установив delims в первый найденный символ / установив его пустым (делая «delims =»).Это НЕ то, чего я хочу, потому что Я ХОЧУ включить разделители, и я хочу, чтобы ИТ разбивал каждую строку ВМЕСТО eol разделял каждую строку.

Зачем вам это нужно?

В некоторой предыстории я собирался использовать команду пропуска, но на странице man для forloop говорится, что опция пропуска пропускает только указанную строку и не позволяет вам сказать;пропустить 3 строки, прочитать одну строку, а затем пропустить еще несколько строк или пропустить по номерам строк.Я мог бы просто использовать один forloop для извлечения одной строки и просто иметь больше forloops или сделать что-то сложное со счетчиками и вложенными циклами, но было бы намного проще, если бы я мог просто разбить токены на каждую строку.

Итак, вот что я хочу

По сути, то, что я хочу, это:

FOR /F "tokens=1,3 delims=<linefeed go here> eol^=" %%A IN ('command 
that prints out multiple lines') DO (echo %%A)

, который выводил бы первую строку и третью строку вывода команды примерно так:

<command output line 1>
<command output line 3>

(если у вас будет хороший пример простой команды, которая печатает как минимум 3 строки, я бы хотел отредактировать это, чтобы более точно отобразить то, что я имею в виду, но я думаю, что выполучить представление).

Так что мой вопрос в основном таков:

A: Можно ли выполнить токенизацию строк, как эта (т.е. указать номера строк для чтения по номерам токенов) B: ЕслиА тогда верно Какой фактический символ перевода строки мне нужно поместить в разделители ?Везде, где я искал, люди, кажется, говорят, что это не следует делать таким образом, но, поскольку они задают немного другой вопрос, это здесь не применимо.Могу ли я использовать номер ASCII для этого?Можно ли настроить его на перевод строки с отключенным eol?

Я видел, как некоторые люди используют:

set $lf=^
delims^=^%$lf%%$lf%^

на форуме DOStips, и я не совсем понимаю, что там происходит,Они устанавливают перевод строки на другого персонажа?Похоже, что они пытаются одновременно использовать и отключать разделители, что для меня не имеет смысла.

Дополнительно: Если я отключаю eol неправильно или что-то еще мешает моему текущему подходу, пожалуйста, сообщите мнеи если вы любезно укажете мне на справочную страницу или что-то подобное, я с радостью сообщу себе, чтобы я не занимал ваше время.

Почему это важно? Потому что это значительно облегчает чтение файлов и захватывает только те строки, которые вы хотите получить из выходных данных команд, вместо того, чтобы проигрывать защиту, размечать строки + пробелы, которые вам даже не нужны, и захватывать только те, которые вы делаете.Делая это таким образом, я могу прямо сказать (я хочу только эти строки), и мне даже не нужно идти или что-то странное, чтобы вырваться из тупика, как только я закончу, хватая все, что мне нужно. В качестве примера для примера можно рассмотреть приведенные ниже строки текста, скажем, я хочу извлечь только e и i из этого «файла». abc def ghi jkl Чтобы сделать это регулярно, мне нужнопропустите первую строку, начните токенизацию, возьмите второй токен, возьмите 6-й токен и вырвитесь, используя goto.Я не хочу считать токен токеном и не хочу использовать goto, чтобы выйти из цикла, когда я закончу.Я просто хочу сказать: «Возьми 2-ю и 3-ю строки и относись к ним немного по-другому».Нет gotos, нет счетных токенов, нет беспорядка Обновление Я попробовал совет по подсказкам

Кстати, это просто попытка получить все строки настроек переноса на моем локальном компьютере (я тестируюпакетный скрипт colleauge)

echo Portopenings check
set $lf=^
FOR /F "tokens=* delims^=^%$lf%%$lf%^ eol^=" %%A IN ('netsh firewall show 
portopening') DO (echo %%A)

Но по какой-то причине он не выдавал никаких ошибок и ничего не выводил.Я ожидал, что он выведет несколько строк, содержащих мои настройки переноса.Выполнение команды в forloop без параметров delims и eol работает нормально, например:

FOR /F "tokens=*" %%A IN ('netsh firewall show portopening') DO (echo %%A)

Обновление 2

Найден этот монстр из Как вы можете найти новую строку в командных файлах?

set NLM=^


set NL=^^^%NLM%%NLM%^%NLM%%NLM%
echo There should be a newline%NL%inserted here.

, который на самом деле работает как задумано (по какой-то причине не забывайте интервал, который приводит к тому, что вышеприведенное не работает, и вместо этого печатаете There should be a newline^^^^inserted here).Единственная проблема в том, что я не могу заставить его работать внутри цикла FOR.Я продолжаю пытаться:

FOR /F "tokens=* delims=%NL% eol^=" %%A IN ('netsh firewall show 
portopening') DO (echo %%A)

с вариациями, но, кажется, ничего не работает вообще.Он просто говорит eol^=" was not expected, а если я уберу "", он говорит syntax incorrect.Я знаю, что мне нужны кавычки, я уверен, что синтаксис eol^= правильный, поэтому я не думаю, что он напрямую связан с этими вещами.Я думаю, что что-то странное происходит с разделителями, приводящими к ошибкам, которые не отражают действительную проблему.

Обновление 3, Кроличья нора

Обратите внимание, что вам нужны определения NL или NLM сверхупопробуйте запустить их (они не работают, хотя) я пробовал:

  for /F "tokens^=1,2 delims^= eol^=^^!NLM^^!" %%i in ('netsh firewall show 
  portopening') do (echo %%i)

  for /F ^"tokens^=1,2 delims^=!NLM! eol^=^" %%i in ('netsh firewall show 
  portopening') do (echo %%i)

  for /F "tokens=1,2 delims^=!NLM! eol=" %%i in ('netsh firewall show 
  portopening') do (echo %%i)

  for /F "tokens=1,2 delims^=!NLM!" %%i in ('netsh firewall show 
  portopening') do (echo %%i)

  for /F "tokens=1,2 delims= eol=" %%i in ('netsh firewall show 
  portopening') do (echo %%i)

  for /F "delims=!NLM! eol=" %%i in ('netsh firewall show 
  portopening') do (echo %%i)

  for /F "delims^=!NLM! eol=" %%i in ('netsh firewall show 
  portopening') do (echo %%i)

  for /F "delims^=!NLM! eol^=" %%i in ('netsh firewall show 
  portopening') do (echo %%i)

  for /F ^"delims^=!NLM! eol^=^" %%i in ('netsh firewall show 
  portopening') do (echo %%i)

  for /F ^"delims^=^!NLM^! eol^=^" %%i in ('netsh firewall show 
  portopening') do (echo %%i)

и кучу других способов, я пробовал все вышеперечисленное с использованием %NLM%и я пытался использовать !NL!, а также %NL% для всех этих.Я попытался опустить опции, перекомбинировать опции, переупорядочить опции, экранирование, не экранирование и все другие комбинации FUN.Большинство из них приводят к синтаксическим ошибкам, некоторые выводят весь вывод с помощью tokens = *, а некоторые печатают некоторые вещи, которые просто не имеют смысла (странный вывод на основе столбцов без тегов, в которых нет разбиений, которые не имеют смысла), но, похоже, они никогда не выводят только определенные данные.линии по токену.Кроме того, на справочной странице указано, что по умолчанию eol установлено значение ;, и оно предназначено для определения, какие строки являются комментариями, а не заканчиваются строкой.Все, что я хочу, это просто чтобы разделитель был символом новой строки, а все остальное не делало ничего странного.Я просто хочу использовать токены для каждой строки вывода или иметь другой простой способ получить только определенные строки.опция Skip практически бесполезна, если я не хочу захватить только одну строку (они ДЕЙСТВИТЕЛЬНО должны были расширить эту функциональность).Я просто не могу обернуть голову вокруг вывода: мне eol=<whatever> следует просто работать.Я даже пытался установить его на Q и @ и - просто для того, чтобы НЕ ИСПОЛЬЗОВАТЬ ЕГО РАЗДЕЛЕННЫЕ ЛИНИИ, но по какой-то причине командная строка ненавидит eol^= и говорит, что это ужасный синтаксис.Даже странно, если я использую delims и eol, но не tokens, я могу опустить "", но если я использую токены, он НИКОГДА не будет работать без кавычек.Еще хуже, я не могу найти точного источника о том, как, черт возьми, на самом деле избежать всего, что нужно для удовлетворения моих потребностей.Все, что я знаю, это то, что eol^= это "" "" ПОДДЕРЖИВАЕТСЯ "" "" чтобы отключить eol.У меня НЕТ ИДЕИ, как это работает, если это работает, или что-то еще, но, попробовав вышеизложенное, я думаю, что 90% ответов по этой теме на другие вопросы должны быть просто неправильными.Даже незнакомец, я могу использовать !NL! и %NL% в эхо-заявлениях, и это прекрасно работает.Попытка использовать его для delims просто не работает.Попытка использовать сырые символы ^ или экранированные символы ^ также не работает.Я даже не знаю, является ли карат символом перевода строки / перевода строки, я просто хочу, чтобы этот символ был разделителем, чтобы КАЖДЫЙ ЖЕТОН ЛИНИИ.Разделы и токены Mybe не связаны, но я ДУМАЛ, что они были связаны.Я думал, что токены были определены разделителями, потому что разделители - это ПО УМОЛЧАНИЮ пространство.Не стесняйтесь обучать меня, я собираюсь взять обед перед тем, как взорваться.

1 Ответ

0 голосов
/ 24 октября 2018

Мммм ... Пара моментов, связанных с этим вопросом.

Важное замечание первое: команда for /F не может сначала прочитать все строки файла. и сохранить их в классе «буфера», а , затем приступить к токенизации буфера на основе символа LF;Команда for /F просто не работает таким образом.

Пожалуйста, внимательно прочитайте написанную вами фразу: "На странице man дополнительно говорится, что по умолчанию используется eol; и для определения, какие строкикомментарии, а не окончание строки ".Опция eol определяет символ, который заставляет игнорировать строки, когда он появляется в начале строки.Точка.

Теперь альтернатива:

set "lines=1 3"
FOR /F "tokens=1* delims=:" %%A IN ('command prints lines ^| findstr /N "^"') DO (
   FOR /F "tokens=1*" %%X in ("!lines!") do (
      IF "%%A" EQU "%%X" (
         echo %%B
         set "lines=%%Y"
      )
   )
)

Рабочий код на основе вашего примера:

@echo off
setlocal EnableDelayedExpansion

set "lines=2 3"
set "selected="
FOR /F "tokens=1* delims=:" %%A IN ('type test.txt ^| findstr /N "^"') DO (
   FOR /F "tokens=1*" %%X in ("!lines!") do (
      IF "%%A" EQU "%%X" (
         set "selected=!selected! %%B"
         set "lines=%%Y"
      )
   )
)

for /F "tokens=2,6" %%A in ("%selected%") do (
   echo Token 2: "%%A"
   echo Token 6: "%%B"
)

test.txt:

a b c
d e f
g h i
j k l

Выход:

Token 2: "e"
Token 6: "i"
...