2016-12-30 2 views
0

У меня есть файл, где каждая строка имеет следующий формат:Извлечение строки из файла с определенными словами, используя партию

1yjo ASN 1 A GLN 3 B 8.85 

я должен извлечь каждую строку, где второй маркер равно PHEи пятых токен равен LEUили наоборот. Например:

2beg LEU 17 A VAL 18 C 8.76 
2beg LEU 17 A PHE 19 A 7.2 
2beg PHE 19 A ALA 21 B 8.88 
2beg PHE 19 D LEU 34 E 13.28 

Если это был входной файл, мне пришлось бы извлечь вторую и четвертую строки. Было бы полезно извлечь их в отдельный файл.

Вот что я пытался до сих пор:

@echo off 
set inputfile=a.dat 
for /F "tokens=1,2,3,4,5,6,7,8" %%a in (%inputfile%) do (
if %%b == "LEU" and %%e == "PHE" do (
@echo %%b %%e 
) 
) 

... но он просто копирует весь входной файл, то есть условие IF не имеет никакого эффекта ...

Редактировать : Я также пробовал:

... 
if %%b == "LEU" (
if %%e == "PHE" (
@echo %%a %%b %%c %%d %%e %%f %%g %%h 
) 
) 
... 

... и он ничего не копирует.

Я также не уверен, если я могу использовать «и» и «или» оператор, или я должен сделать это с несколькими вложенными, если в ...

Как я могу это сделать?

ответ

2

Я только что нашел решение:

@echo off 
for /F "tokens=1,2,3,4,5,6,7,8" %%a in (%1) do (
    if "%%b" == "%2" (
     if "%%e" == "%3" (
      @echo %%a %%b %%c %%d %%e %%f %%g %%h >> output.txt 
     ) 
    ) 
    if "%%b" == "%3" (
     if "%%e" == "%2" (
      @echo %%a %%b %%c %%d %%e %%f %%g %%h >> output.txt 
     ) 
    ) 
) 

Я также использовал входные параметры для имени входного файла (% 1) и две строки (% 2 и% 3) и он работает как a charm :)

+0

Это не сохранит первоначальный интервал токенов. Это не составит труда исправить, но есть намного более простые и быстрые способы, чем FOR/F. – dbenham

1

Чтобы извлечь подходящие строки, я бы просто использовал базовую трубу.

Как это в CMD окно:

Find " LEU "<"a.dat"|Find " PHE ">Output.txt 

... или это из пакетного файла:

@Find " LEU "<"a.dat"|Find " PHE ">Output.txt 

[Edit /]

В качестве обновления на основе комментарии ниже, вот моя идея, используя findstr в пакетном файле:

@FindStr/RC:"\<LEU .* PHE\>" /C:"\<PHE .* LEU\>" a.dat>Output.txt 
+0

+1, Сначала я думал, что это будет недостаточно ограничительным. Но потом я понял, что очень маловероятно, что PHE или LEU могут появляться где угодно, кроме 2-го и/или 5-го жетонов. Но я предпочитаю использовать один FINDSTR вместо нескольких FIND – dbenham

+0

Я изначально планировал использовать findstr, _ (аналогично тому, что вы опубликовали) _, но из-за общей привычки к изменению параметров параметра после получения решения я решил чтобы сделать его максимально простым. – Compo

1

Вы можете очень эффективно (быстро) получить ответ с одного Findstr поиска регулярных выражений, хотя поиск неудобно из-за искалеченных регулярные возможности экспрессии Findstr. Я предполагаю, что это всегда промежутки между токенами, а не вкладки. Я использовал продолжение строки, чтобы упростить чтение команды.

findstr /r /c:"^[^ ][^ ]* *PHE *[^ ][^ ]* *[^ ][^ ]* *LEU "^ 
      /c:"^[^ ][^ ]* *LEU *[^ ][^ ]* *[^ ][^ ]* *PHE " input.txt >output.txt 

Если вы можете рассчитывать на то, что НОУ и РНЕ никогда не появляются нигде, кроме 2-го и/или 5 жетонов, то вы можете значительно упростить поиск, как:

findstr "PHE.*LEU LEU.*PHE" input.txt >output.txt 

Точный поиск намного проще с помощью правильного инструмента регулярного выражения. Вы можете использовать powershell или JScript для решения регулярного выражения для собственных скриптов. Или вы можете загрузить версию grep для Windows или ...

Поскольку у меня уже есть это, я бы использовал свой JREPL.BAT regular expression utility. JREPL - это чистый скрипт (гибридный пакет/JScript), который запускается изначально на любой машине Windows с XP и дальше - не требуется сторонний exe-файл. Полная документация доступна в командной строке через jrepl /?, или jrepl /?? для получения справки.

jrepl "^\S+\s+(PHE|LEU)\s+\S+\s+\S+\s+(?!\1)(PHE|LEU)\s" "" /k 0 /f input.txt /o output.txt 

В случае, если вы не знакомы с регулярными выражениями:

  • ^ знаменует собой начало строки
  • \S+ соответствует одному или более не-пробельных символов (любой произвольный маркер)
  • \s+ представляет один или несколько символов пробела (разделители токенов)
  • (PHE|LEU) matche s PHE или LEU, и фиксирует совпадение
  • (?!\1) - отрицательный прогноз вперед, который терпит неудачу, если следующая строка соответствует ранее зафиксированному совпадению. (не хотите соответствовать PHE-PHE или LEU-LEU)

Обычно JREPL используется для поиска/замены строк. Параметр /k 0 указывает JREPL игнорировать аргумент replace и просто распечатывать все строки, соответствующие строке поиска.

Такое же регулярное выражение может использоваться с большинством любого подходящего инструмента регулярного выражения.

1

Это то же решение vtomic85, но более простым и быстрым способом. Эта версия также сохраняет исходный интервал.

@echo off 
(for /F "delims=" %%a in (%1) do (
    for /F "tokens=2,5" %%b in ("%%a") do (
     if "%%b%%c" equ "%2%3" echo %%a 
     if "%%b%%c" equ "%3%2" echo %%a 
    ) 
)) > output.txt 
Смежные вопросы