Удаление (возможно, вложенных) текстовых кавычек в командной строке

Я столкнулся с этой проблемой на сервере с более ранней версией OpenSSH.Я управляю сервером и решил проблему, создав два CNAME в моей именованной конфигурации:

realhost.myexample.com.      IN  A       XXX.XXX.XXX.XXX
realhost2.myexample.com.     IN  CNAME   realhost.myexample.com.
realhost3.myexample.com.     IN  CNAME   realhost.myexample.com.

Затем в моей локальной конфигурации клиента ssh:

ControlMaster auto
ControlPath ~/.ssh/%r_%p_%h

host realhost
hostname realhost.myexample.com

host realhost2
hostname realhost2.myexample.com

host realhost3
hostname realhost3.myexample.com

Оператор ControlPath таков, что имена управляющих сокетов не наступают друг на друга .

Вот и все, но чтобы упростить управление, я написал сценарий оболочки для 'ssh' на стороне клиента. Он понимает, что существуют «группы» хостов (в этом случае realhost, realhost1, realhost2 составляют одну группу). При выдаче sshwrapper realhost, если нет открытых каналов, открываются все три и начинается один сеанс. При следующем запуске он подсчитывает количество открытых подключений на канал и открывает новый сеанс в канале с наименьшим количеством подключений.

С одним реальным и двумя «фальшивыми» хостами я могу подключиться 30 раз, прежде чем получу ошибку. Вход в систему происходит очень быстро, за исключением того, что начальное время занимает секунду или две, так как в это время открываются все три канала управления.

2
01.03.2019, 13:19
4 ответа

Если вы знаете, что ввод не содержит символов <или >, вы можете сделать:

sed '
  # replace opening quote with <
  s|\[quote=[^]]*\]|<|g
  # and closing quotes with >
  s|\[/quote\]|>|g
  :1
    # work our way from the inner quotes
    s|<[^<>]*>||g
  t1'

Если он может содержать символы <или >, вы можете избежать их, используя схему, подобную:

sed '
  # escape < and > (and the escaping character _ itself)
  s/_/_u/g; s/</_l/g; s/>/_r/g

  <code-above>

  # undo escaping after the work has been done
  s/_r/>/g; s/_l/</g; s/_u/_/g'

С perlс использованием рекурсивных регулярных выражений:

perl -pe 's@(\[quote=[^\]]*\](?:(?1)|.)*?\[/quote\])@@g'

Или даже, как вы упомянули:

perl -pe 's@(\[quote=.*?\](?:(?1)|.)*?\[/quote\])@@g'

С помощью perlвы можете обрабатывать многострочный ввод, добавляя опцию -0777. С sedвам нужно будет добавить к коду префикс :

.
:0
$!{
  N;b0
}

Чтобы загрузить весь ввод в пространство шаблонов.

3
27.01.2020, 22:02

Небольшой скрипт, который увеличивает переменную счетчика для каждой начальной -кавычки и уменьшает ее для каждой конечной -кавычки. Если переменная-счетчик больше 0, то текстовые фрагменты пропускаются.

#!/bin/bash

# disable pathname expansion
set -f    
cnt=0
for i in $(<$1); do
        # start quote
        if [ "${i##[quote=}" != "$i" ] && [ "${i: -1}" = "]" ]; then
                ((++cnt))
        elif [ "$i" = "[/quote]" ]; then
                ((--cnt))
        elif [ $cnt -eq 0 ]; then
                echo -n "$i "
        fi
done
echo

Выход:

$ cat q1
text part 1 [quote=foo] outer quote 1 [quote=bar] inner quote [/quote] outer quote 2 [/quote] text part 2 [quote=foo-bar] next quote [/quote] text part 3
$./parse.sh q1
text part 1 text part 2 text part 3
$ cat q2
text part 1 [quote=foo] outer quote 1 [quote=bar] inner quote [foo] [/quote] outer quote 2 [/quote] text part 2 [quote=foo-bar] next quote [/quote] text part 3
$./parse.sh q2
text part 1 text part 2 text part 3
0
27.01.2020, 22:02

Я проверил это, и оно у меня сработало. Возможно, вы захотите выбрать другой временный шаблон вместо foobar. Без него sedудалил все между тегами, оставив толькоtext part 1 text part 3

sed -e 's/\/quote\]/foobar\]/3' -e 's/\[.*\/quote\]//' -e 's/\[.*foobar]//' testfile

вместо этого, если testfileвы можете просто передать это с помощьюcat

0
27.01.2020, 22:02

Вы можете сделать это с помощью POSIX sed, как описано здесь. Обратите внимание, что это решение применимо к обоим типам показанных вами входных данных. Ограничения: ввод не является многострочным, так как мы используем новые строки в качестве маркеров для эффекта. требуется трансформация.

$ sed -e '
      :top
      /\[\/quote]/!b
      s//\
&/
      s/\[quote=/\
\
&/

     :loop
        s/\(\n\n\)\(\[quote=.*\)\(\[quote=.*\n\)/\2\1\3/
     tloop

     s/\n\n.*\n\[\/quote]//
     btop
 '  input.txt
0
27.01.2020, 22:02

Теги

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