Как я могу включать информацию в строку выше при поиске шаблона в строке?

Я должен дифференцироваться между первым изображением и вторыми сценариями изображения когда retrieveing информация с помощью grep. Они оба - created_at, но каждый для изображения, и каждый для твита. Все у тех для твита есть a }, в строке выше так я думал, что мог использовать ту информацию однако, я не уверен, как я мог сделать это.

Вот grep, который я использую:

grep -wirnE 'Wed Oct 19 2(1:[0-5][0-9]:[0-5][0-9]|2:([0-2][0-9]:[0-5][0-9]|30:00)) .* 2016' *

enter image description here

enter image description here

1
задан 27 September 2017 в 10:18

2 ответа

Можно использовать опции -A1 и -B1 позволить grep распечатать строку после (-A) и прежде (-B) согласующий отрезок длинной линии. Попробуйте следующую командную строку,

grep -B1 created_at log-file|grep -A1 '^}'|grep created_at

я протестировал со следующим входным файлом, названным log-file

asdf
qwerty
...
},
"created_at" "date-with-near-}"
zxcv
some other string
"created_at" "date-without-}"
...

последовательность Тестирования

$ grep -B1 created_at log-file
},
"created_at" "date-with-near-}"
--
some other string
"created_at" "date-without-}"

$ grep -B1 created_at log-file|grep -A1 '^}'
},
"created_at" "date-with-near-}"

$ grep -B1 created_at log-file|grep -A1 '^}'|grep created_at
"created_at" "date-with-near-}"
2
ответ дан 3 December 2019 в 06:53

Можно использовать sed N управляйте для чтения нескольких строк в пространство шаблона.

Найти первый:

sed -nr '/\}/N; /.*\}.*\n.*"Wed Oct 19 .* 2016/Ip' file

и удалить предыдущую строку:

sed -nr '/}/N; s/.*}.*\n(.*"Wed Oct 19 .* 2016)/\1/Ip' file

Проблема - это sed не скажет Вам, которые регистрируют строку, от, и она не имеет рекурсивного флага поиска файла (afaik). Это может обойтись путем включения рекурсивного globbing с ** в оболочке (но, "из какого файла это прибывало?" проблема остается):

shopt -s globstar
sed -nrs '/}/N; s/.*}.*\n(.*"Wed Oct 19 .* 2016)/\1/Ip' **

С несколькими файлами добавьте -s флаг для создания sed рассмотрите поток как отдельные файлы (для предотвращения нежелательных многострочных соответствий), можно добавить подробное выражение в середине...

sed -nrs '/}/N; s/.*}.*\n(.*"Wed Oct 19 2(1:[0-5][0-9]:[0-5][0-9]|2:([0-2][0-9]:[0-5][0-9]|30:00)) .* 2016)/\1/Ip' **

Для второго возникновения без } на предыдущей строке

sed -nr '/^[^}]*$/N; /.*\n.*"Wed Oct 19 .* 2016/Ip' file

и удаление предыдущей строки:

sed -nr '/^[^}]*$/N; s/.*\n(.*"Wed Oct 19 .* 2016)/\1/Ip' file

Объединить это во что-то более полезное:

for f in **; do [[ -f "$f" ]] && echo -e ""$f":\n tweet: $(sed -nr '/}/N; s/.*}.*\n(.*"Wed Oct 19 .* 2016)/\1/Ip' "$f")\n image: $(sed -nr '/^[^}]*$/N; s/.*\n(.*"Wed Oct 19 .* 2016)/\1/Ip' "$f")"; done 

или... немного больше четко (!)

#!/bin/bash
shopt -s globstar

for f in **; do 
   [[ -f "$f" ]] && 
   echo -e ""$f":\n tweet: $(sed -nr '/}/N; s/.*}.*\n(.*"Wed Oct 19 .* 2016)/\1/Ip' "$f")"
done 

Это дает выходное сходство с:

file1:
 tweet: "created_at": "Wed Oct 19 12:36:54 +0000 2016"
 image: "created_at": "Wed Oct 19 somethingsomething 2016"
file2:
 tweet: "created_at": "Wed Oct 19 random-chars 2016"
 image: "created_at": "Wed Oct 19 whatever 2016"

Если Вы хотите исключить один или другой, удалите соответствующую часть из сценария, например, получить только твит...

for f in **; do 
   [[ -f "$f" ]] && 
   echo -e ""$f":\n tweet: $(sed -nr '/}/N; s/.*}.*\n(.*"Wed Oct 19 .* 2016)/\1/Ip' "$f")"
done

Примечания

  • sed -n будьте тихи, пока мы не просим вывод - это используется в сочетании с p команда печати для имитации действия grep
  • -r используйте расширенный regex
  • /}/N найдите строку с } и считайте следующую строку в пространство шаблона
  • /^[^}]*$/N найдите строку без } и считайте следующую строку в пространство шаблона
  • I поиск без учета регистра
  • p распечатайте, находил/редактировал строки
  • s/old/new замена old с new
2
ответ дан 3 December 2019 в 06:53

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

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