Найти файлы с определенным 2-строчным шаблоном с помощью awk

AppArmor включен по умолчанию.

1
задан 7 May 2014 в 14:38

5 ответов

Как насчет

for file in *.txt; do 
    grep -A1 "@<TRIPOS>BOND" "$file" | grep -q SUBSTR && mv "$file" bad_files/
done

Объяснение:

Это будет проходить через все .txt файлы в текущем каталоге (изменение на blob до любых совпадений с вашими файлами) и сохранение каждый как $file. Затем он выполнит поиск $file для @<TRIPOS>BOND и распечатает его и следующую строку. Это передается через следующий grep, который молча (-q) ищет SUBSTR, если он находит его, это означает, что строка после BOND равна SUBSTRUCTURE, а не цифра, которую вы хотите, чтобы она переместите текущий файл в папку bad_files.

3
ответ дан 24 May 2018 в 08:04

Это не так просто:

find -type f -exec \
 awk '/@<TRIPOS>BOND/{getline; \
  if ($0 !~ /1  3  5  ar/){\
  printf "mv %s /path/to/move/%s\n", FILENAME, FILENAME}}' {} \; \
| bash

Объяснение:

find -type f: Найти все файлы в текущем рабочем каталоге awk '/@<TRIPOS>BOND/{getline; \: найти строку внутри файла и перейдите к следующей строке if ($0 !~ /1 3 5 ar/){\: если следующая строка НЕ ​​(!~), ваша желаемая «цифровая строка» printf "mv %s /path/to/move/%s\n", FILENAME, FILENAME}}' {} \; \: постройте команду mv и запустите ее ... | bash: ... bash и выполните его.

Таким образом, команда будет mv всем файлом, который не связывает числовую строку с каталогом /path/to/move/.

0
ответ дан 24 May 2018 в 08:04
  • 1
    Я думаю, что числовая строка OP может измениться. Я сомневаюсь, что это будет одинаково для всех облигаций. – terdon♦ 7 May 2014 в 15:55
  • 2
    Затем он может заменить if ($0 !~ /1 3 5 ar/) на if ($0 ~ /@<TRIPOS>SUBSTRUCTURE/) – chaos 7 May 2014 в 16:24
  • 3
    В самом деле. Или, проще if ($1 !~ /^[0-9]$/), вам не нужно беспокоиться о нескольких пробелах или вкладках. – terdon♦ 7 May 2014 в 16:27
  • 4
    Вы должны изменить эту часть if ($0 !~ /1 3 5 ar/) – A.B. 4 July 2015 в 01:32
[F1]
0
ответ дан 24 May 2018 в 08:04
  • 1
    трубопровод к bash не нужен, мы можем использовать функцию system (). Пожалуйста, проверьте мой ответ – Sergiy Kolodyazhnyy 3 July 2015 в 21:11
  • 2
    -1 у вас БОЛЬШАЯ проблема, если имя файла содержит пробелы и другие забавные символы. – A.B. 4 July 2015 в 01:29

Задача довольно проста с помощью awk. Вот мой пример. Я создал два файла file-nm (для не пропущенных) и file-m (для отсутствующих) и каталог moved для файлов, которые мы хотим переместить.

awk '/@<TRIPOS>BOND/ {getline; if ($0 == "@<TRIPOS>SUBSTRUCTURE" ) system("mv \""FILENAME"\" moved")}' file-nm file-m

Здесь мы найдем строку @<TRIPOS>BOND, переходим к следующей строке и проверяем, является ли эта строка @<TRIPOS>SUBSTRUCTURE. Если это так, мы делаем системный вызов с «mv» FILENAME файла, который был найден, и «перемещен» в качестве адресата. Вот результат:

$ ls
file-m  file-nm  moved


$ awk '/@<TRIPOS>BOND/ {getline; if ($0 == "@<TRIPOS>SUBSTRUCTURE" ) system("mv \""FILENAME"\" moved")}' file-nm file-m      


$ ls                                                                                                                     
file-nm  moved


$ ls moved                                                                                                               
file-m
0
ответ дан 24 May 2018 в 08:04
  • 1
    Вы должны использовать двойные кавычки для ваших имен файлов в system (…) – A.B. 4 July 2015 в 00:59
  • 2
    @ A.B. Если я использую "FILENAME" , команда system будет буквально рассматривать это как mv FILENAME moved. Unquoted FILENAME получает замену awk, из имени файла файла – Sergiy Kolodyazhnyy 4 July 2015 в 01:03
  • 3
    [F1] – A.B. 4 July 2015 в 01:05
  • 4
    @ A.B. Это работает :) Спасибо – Sergiy Kolodyazhnyy 4 July 2015 в 01:07

Использование awk или gawk

awk '/@<TRIPOS>BOND/,/@/ {getline; if ($_ ~ /^@/) {printf "%s:%s\n",$_,FILENAME; system ("mv \""FILENAME"\" <bad_files>/$(basename \""FILENAME"\")")} exit}' <file_name>

Пояснение

/@<TRIPOS>BOND/,/@/ Нам нужен только блок между @<TRIPOS>BOND и следующая строка, начиная с @ getline Прочитать следующую строку после @<TRIPOS>BOND if ($_ ~ /^@/) Проверить, если строка начинается с @ true Печать сообщения
printf "%s:%s\n",$_,FILENAME
Переместить файл
system ("mv \""FILENAME"\" <bad_files>/$(basename \""FILENAME"\")")
false Оставьте скрипт
exit

Пояснение

$ cat foo
@<TRIPOS>ATOM
  2 H18 65.2220 Du 1 RES1 0.0000
@<TRIPOS>BOND
@<TRIPOS>SUBSTRUCTURE

$ cat bar
@<TRIPOS>ATOM
  2 H18 65.2220 Du 1 RES1 0.0000
@<TRIPOS>BOND
 1  3  5  ar
@<TRIPOS>SUBSTRUCTURE

$ awk '/@<TRIPOS>BOND/,/@/ {getline; if ($_ ~ /^@/) {printf "%s:%s\n",$_,FILENAME; system ("mv \""FILENAME"\" \""FILENAME"\"_moved")} exit}' foo
@<TRIPOS>SUBSTRUCTURE:foo

$ awk '/@<TRIPOS>BOND/,/@/ {getline; if ($_ ~ /^@/) {printf "%s:%s\n",$_,FILENAME; system ("mv \""FILENAME"\" \""FILENAME"\"_moved")} exit}' bar

$ cat foo_moved 
@<TRIPOS>ATOM
  2 H18 65.2220 Du 1 RES1 0.0000
@<TRIPOS>BOND
@<TRIPOS>SUBSTRUCTURE

$ cat bar_moved
cat: bar_moved: No such file or directory
0
ответ дан 24 May 2018 в 08:04

Другие вопросы по тегам:

Похожие вопросы: