unix - удалить (i) пустое пространство между одиночными символами и (ii) более X последовательных вхождений слова - PullRequest
0 голосов
/ 09 ноября 2018

Я бы хотел

(i) заменять пробел между символами, только если эти символы одинарные ; например,

Down [Enter] p s -- a u x [Delete] 

должно стать

Down [Enter] ps -- aux [Delete] 

(ii) удалить слова, которые последовательно повторяются более X раз, до тех пор, пока не произойдет любая другая вещь, не являющаяся словом, так что (скажем, X = 2)

 [Delete] [Delete] [Delete] [Delete] [Delete] [Delete] ab inition [Delete] [Delete] [Delete] [Delete] [Delete] [Delete] ab definitio

становится

 [Delete] [Delete] ab initio [Delete] [Delete] ab definitio

спасибо!

1 Ответ

0 голосов
/ 11 ноября 2018

Вы не получили много ответов. Я думаю, что главной причиной является сочетание двух разных вопросов, оба нетривиальных. Обычно это помогает продемонстрировать ваши собственные усилия, но я понимаю, что ваши усилия могли часами думать, «с чего начать».

Первый вопрос, устранение пробелов между одиночными символами, может быть выполнен с помощью цикла в sed:

echo 'Down [Enter] p s -- a u x [Delete] ' | 
   sed -r ':a;s/( [^ ]|\r) ([^ ])( |$)/\1\2\r\3/;ta; s/\r//g'
Down [Enter] ps -- aux [Delete]

Пояснение: При прямом подходе a u x изменится на au x после первой замены, а другое пространство будет забыто. Вам нужно пройти через замены более одного раза и помнить, что буква u в au x была одиночной в исходной строке.
Для запоминания мест, где была произведена замена, мы используем \r (и удалим его позже).

:a; Метка для следующей замены.
( [^ ]|\r) Пробел, за которым следует буква ИЛИ наш временный \r маркер
([^ ]) Пробел, за которым следует буква
( |$) Пробел или конец строки
/\1\2\r\3/ Заменить двумя запомненными символами, вставить специальный маркер и пробел, если он не был последним символом строки.
ta Вернуться к тегу начала цикла :a, когда что-то было заменено
s/\r//g' Удалите наши временные маркеры.

Второй вопрос тоже сложный. Следующее решение близко, но неверно:

for (( X=2; X<8; X++)); do
  echo "X=$X (incorrect solution)"
  echo 'some some some some some some some some some some some input' |
     sed -r 's/([^ ]+[ ]+)(\1{'${X}'})(\1+)/\2/g'
done

Проблема в том, что повторяющаяся строка также появляется в другом месте, как в
some some some input some some some или хуже some some some input input input.

Я не вижу простого решения для sed решения, но awk поможет здесь.
Для подсчета повторяющихся полей мое решение рассматривает каждое слово как одну запись.

for (( X=2; X<8; X++)); do
   echo "X=$X"
   echo 'some some some some some some some some some some some input some some some some' |
      awk -v x=$X 'BEGIN {RS="[ \n]"; ORS='\n'; repeated=1}
         { if (last==$0)
             repeated++;
           else
             repeated=1;
         }
         {last=$0}
         repeated <= x {print $0" "}
         END {print "\n"}
      '
done
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...