sed удалить строки, содержащие точное количество определенных символов

У меня почти точная настройка и проблема.

Насколько я могу судить, сеть с пространством имен просто не хочет, чтобы к ней был доступ извне. Вероятно, существует какое-то правило iptables, которое позволяет сопоставлять 192.168.1.*:9091с 10.200.200.2:9091, но я прибегал к использованиюsocatв качестве обходного пути, чтобы сделать сеть 10.200.200.*доступной через фактический IP-адрес,192.168.1.*

Я предполагаю, что 10.200.200.2— это IP-адрес, к которому привязан демон передачи rpc в пространстве имен nordvpn. Вы должны получить эту информацию, используя ip netns exec nordvpn ifconfig vpn1. Найдите значение inet addr.

Вы можете убедиться, что служба rpc работает, используя ip netns exec nordvpn transmission-remote --auth : -siдля получения информации о сеансе.

Затем соедините виртуальную сеть и реальную сеть для порта 9091с помощью socat :

.

socat tcp-listen:9091,reuseaddr,fork tcp-connect:10.200.200.2:9091

Вы также можете превратить его в демона для бедняков, запустив его как запланированное задание, используяat

echo 'socat tcp-listen:9091,reuseaddr,fork tcp-connect:10.200.200.2:9091 > /dev/null 2>&1' | at now

Обратите внимание, что аргумент forkдля socatсоздает несколько дочерних процессов. Вы можете остановить их позже, используяpkill -f 'socat tcp-listen:9091'

После этого вы сможете получить к нему доступ со своего рабочего стола, используя IP-адрес Ubuntu Box.

1
22.07.2019, 21:41
4 ответа

Если вы должны использовать sed, команда будет:

sed -E -- '\-^([^/]*/[^/]*){3}$-d'

Но если вам не требуется использовать sed, самое простое решение использует grep.

Замените N в этой команде на желаемое значение N:

egrep -vx '([^/]*/[^/]*){N}'

grepимеет параметр командной строки -v, который заставляет grepотображать все строки, которые не соответствуют регулярному выражению. Таким образом, задача состоит в том, чтобы создать регулярное выражение, которое соответствует строкам, содержащим ровно N вхождений символа косой черты, а затем использовать grep -vс этим регулярным выражением.

Один пример — шаблон:

[^/]*/[^/]*

N экземпляров — шаблон:

([^/]*/[^/]*){N}

Ровно N экземпляров является шаблоном:

^([^/]*/[^/]*){N}$

Для шаблонов, предназначенных для соответствия только целым строкам, как этот, grepтакже имеет параметр командной строки -x.

Итак, пусть N равно 3. Соответствует ли наше регулярное выражение только строкам с 3 экземплярами /?

$ cat << EOF | egrep -x '([^/]*/[^/]*){3}'
/
//
///
////
/stuff
/stuff/added
/stuff/added/
/stuff/added/to/
/stuff/added/to/each
/stuff/added/to/each/line
more/stuff
more/stuff/added
more/stuff/added/
more/stuff/added/to/
more/stuff/added/to/each
more/stuff/added/to/each/line
consecutive//slashes/
/consecutive//slashes/
/consecutive//slashes
///all in one place
all in one place///
all in ///one place
EOF
///
/stuff/added/
more/stuff/added/
consecutive//slashes/
/consecutive//slashes
///all in one place
all in one place///
all in ///one place

Да, кажется, что наше регулярное выражение соответствует правильным строкам. Теперь мы просто добавляем флаг -vк , отфильтровываем совпадающие строки и отображаем строки, которые не совпадают.

$ cat << EOF | egrep -vx '([^/]*/[^/]*){3}'
/
//
///
////
/stuff
/stuff/added
/stuff/added/
/stuff/added/to/
/stuff/added/to/each
/stuff/added/to/each/line
more/stuff
more/stuff/added
more/stuff/added/
more/stuff/added/to/
more/stuff/added/to/each
more/stuff/added/to/each/line
consecutive//slashes/
/consecutive//slashes/
/consecutive//slashes
///all in one place
all in one place///
all in ///one place
EOF
/
//
////
/stuff
/stuff/added
/stuff/added/to/
/stuff/added/to/each
/stuff/added/to/each/line
more/stuff
more/stuff/added
more/stuff/added/to/
more/stuff/added/to/each
more/stuff/added/to/each/line
/consecutive//slashes/
3
27.01.2020, 23:10

Одним из способов сделать это может быть:

  • попытаться заменить (подставить )(N+1)е вхождение символа; если замена прошла успешно, начать новый цикл (разветвить)

  • попытаться заменить (подставить )Nое вхождение символа; если замена не удалась, начать новый цикл (разветвить)

(иначе)

  • удалить строку

Использование GNU sed и взятие N = 2:

$ printf 'foo/\nfoo/bar/\nfoo/bar/baz/\n' | sed -e 's,/,/,3;t' -e 's,/,/,2;T' -ed
foo/
foo/bar/baz/
2
27.01.2020, 23:10

Вы также можете использовать awk :, указать /в качестве разделителя полей и искать поля n+1.

awk -F'/' -v n=3 'NF != n + 1' file
4
27.01.2020, 23:10

Вы можете подойти к этому пбм. следующим образом:

$ perl -ne 'tr|/|/| == 3 || print' inp

Здесь мы полагаемся на свойство функции Perl trвозвращать количество переводов, которые она сделала для входной строки, в данном случае текущей записи. Поэтому, когда во входной записи ровно три косых черты, мы не печатаем эту запись, но во всех остальных случаях печатаем.

Другим методом, на этот раз использующим POSIX sed, может быть:

$ sed -e 's:/:/:4;t' -e 's//\n/3' -e '/\n/d' inp

Здесь мы сначала проверяем, есть ли более 3 косых черт, и если да, мы переходим к концу кода sed с пространством шаблонов. OTW, 3 или меньше косых черт будут присутствовать в пространстве шаблона. Теперь мы проверяем, можно ли заменить третью косую черту новой строкой \nв пространстве шаблонов. Если после этой подстановки мы видим перевод строки => во вводе было ровно три косых черты. Поскольку мы не хотим видеть ровно 3 слэша, мы удаляем это пространство шаблона. OTW, все, что осталось (=> шаблонное пространство с 2 или меньшими косыми чертами )выводится на стандартный вывод.

Примечание:\nв этом последнем случае найти не удалось, так как замена s//\n/3не удалась.

Еще одним методом, использующим POSIX sed, является:

$ sed -e h -e 's|[^/]||g' -e '/^.\{3\}$/d' -e g inp

Сохраните копию текущей записи и удалите все символы без косой черты. Теперь проверьте, есть ли ровно три символа (на самом деле, теперь они все )косые черты в пространстве шаблона. Если да, мы сразу же удаляем его. OTW, вызовите сохраненную запись из хранилища, а затем sed распечатает ее по умолчанию для вас.

ХТН.

4
27.01.2020, 23:10

Теги

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