Удалить последовательные строки, содержащие один и тот же шаблон - PullRequest
0 голосов
/ 02 июля 2018

Я хотел бы создать sed (или эквивалентное) выражение, которое удаляло бы последовательные строки, содержащие определенный символ. Например, у меня есть список IP-адресов, за которыми следует двоеточие. Если они содержат значение, следующая строка (и) не будет содержать двоеточие. Если есть последовательные строки с двоеточиями, первую следует удалить (поскольку они пусты), как показано ниже:

+159.0.0.0: 
+159.0.0.1: 
+443/tcp open https
+159.0.0.2: 
+159.0.0.3: 
+159.0.0.4: 
+159.0.0.5: 
+80/tcp open http
+443/tcp open https

Желаемый результат:

+159.0.0.1: 
+443/tcp open https
+159.0.0.5: 
+80/tcp open http
+443/tcp open https

Ответы [ 4 ]

0 голосов
/ 03 июля 2018

sed для s / old / new, ЭТО ВСЕ . Это будет работать с любым awk в любой оболочке на любой машине UNIX:

$ awk '/:/{s=$0 ORS;next} {print s $0; s=""}' file
+159.0.0.1:
+443/tcp open https
+159.0.0.5:
+80/tcp open http
+443/tcp open https

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

$ cat file
+159.0.0.0:
+159.0.0.1:
+443/tcp open https
+159.0.0.2:
+159.0.0.3:
+159.0.0.4:
+159.0.0.5:
+80/tcp open http
+443/tcp open https
+159.0.0.6:

$ awk '/:/{s=$0 ORS;next} {print s $0; s=""} END{printf "%s", s}' file
+159.0.0.1:
+443/tcp open https
+159.0.0.5:
+80/tcp open http
+443/tcp open https
+159.0.0.6:
0 голосов
/ 02 июля 2018

Еще один awk:

$ awk '/:/ { p = $0 } $0 !~ /:/ {if (p) {print p} print $0; p = ""} ' file
+159.0.0.1:
+443/tcp open https
+159.0.0.5:
+80/tcp open http
+443/tcp open https
0 голосов
/ 02 июля 2018

Это может сработать для вас (GNU sed):

sed 'N;/:.*\n.*:/!P;D' file

Держите движущееся окно из двух строк, и если обе строки содержат :, не печатайте первую.

0 голосов
/ 02 июля 2018

РЕДАКТИРОВАТЬ: Чтобы проверить, что в последней строке двоеточие или нет, немного измените код, как показано ниже.

awk '!/:/ && prev{print prev ORS $0;prev="";next} {prev=$0} END{if(prev && prev !~ /:/){print prev}}' Input_file


Полностью протестировано на предоставленном образце. Пожалуйста, попробуйте выполнить следующее и дайте мне знать, если это вам поможет.

awk '!/:/ && prev{print prev ORS $0;prev="";next} {prev=$0} END{if(prev){print prev}}' Input_file

Теперь добавляем не одну линейную форму решения.

awk '
!/:/ && prev{
  print prev ORS $0;
  prev="";
  next
}
{
  prev=$0
}
END{
  if(prev){
    print prev}
}'  Input_file

Объяснение: Добавление объяснения для вышеприведенного кода тоже сейчас.

awk '
!/:/ && prev{          ##Checking condition here if a line is NOT having colon in it and variable prev is NOT NULL then do following.
  print prev ORS $0;   ##Printing the value of variable named prev ORS(whose default value is new line) and then current line by $0.
  prev="";             ##Nullifying prev variable value here.
  next                 ##Using awk out of the box next keyword which will skip all further statements from here.
}
{
  prev=$0              ##Setting value of variable prev to current line here.
}
END{                   ##Starting END section of current code here, which will be executed after Input_file is being read.
  if(prev){            ##Checking if variable prev is NOT NULL, if yes then do following.
    print prev}        ##Printing the value of variable prev here.
}' Input_file          ##Mentioning Input_file name here.
...