Sed многократное перемещение в линии - PullRequest
0 голосов
/ 04 июня 2018

Это может быть очень простой вопрос, но я не могу сформировать sed для лайнера для этого.

Рассмотрим эту строку

foo@some_text/48183 bar@another-test/22787 xyz@some_another_text/2291

Я хочу заменить все на "@"в пространство через запятую.Таким образом, мой ожидаемый результат должен выглядеть следующим образом:

foo,bar,xyz

Я пытался sed -e 's/@.*[^ ]/,/g' заменить до пробела, однако он заменяет целую строку (не очень хорошо в написании регулярного выражения).

ЛюбойПомощь будет оценена.

Ответы [ 4 ]

0 голосов
/ 04 июня 2018

Вы также можете сделать это наоборот, даже если это может быть немного больше pipy.

$ echo "foo@some_text/48183 bar@another-test/22787 xyz@some_another_text/2291" | (tr ' ' ',' | grep -oP '(?=,|^)[^@]+' | tr -d '\n'; echo "")
foo,bar,xyz

Вместо замены части строки вы можете напрямую извлечь соответствующие части.

Пояснения:

  • tr ' ' ',', чтобы заменить все пробелы запятыми.
  • grep -oP '(?=,|^)[^@]+', чтобы получить все до @.Он использует регулярное выражение perl с lookaround (наложение ограничения на то, что предыдущий символ является либо запятой, либо началом строки, и принимает все символы, кроме @.
  • tr -d '\n', используется для удаления вставленного EOLна grep
  • echo "" может быть опущено, если вам не нужно иметь окончание \n. Затем вы можете упростить команду в tr ' ' ',' | grep -oP '(?=,|^)[^@]+' | tr -d '\n'
0 голосов
/ 04 июня 2018

Вы можете найти и перехватить любые 1+ символов, кроме @, перед @ символом, затем сопоставить @ и любые 0+ символов, кроме пробелов, с последующими 0+ символами пробелов, и заменить все эти символы назаполнитель для группы 1 и запятая.Затем вам придется удалить запятую.

См. sed demo :

s='foo@some_text/48183 bar@another-test/22787 xyz@some_another_text/2291'
echo "$s" | sed -E 's/([^@]+)@[^[:space:]]*[[:space:]]*/\1,/g' | sed 's/,$//'

Обратите внимание, что вы также можете использовать sed 's/\([^@][^@]*\)@[^[:space:]]*[[:space:]]*/\1,/g' вставку из POSIX.ERE версия.В BRE POSIX вы должны экранировать ( и ), чтобы сформировать группу захвата, а квантификатор + должен быть экранирован или заменен конструкцией aa*.

Подробности

  • ([^@]+) - Группа захвата 1: 1+ символов, отличных от @
  • @ - @ char
  • [^[:space:]]*- 0+ символов, отличных от пробелов
  • [[:space:]]* - 0+ символов пробелов

\1 - это заполнитель для текста, захваченного группой захвата # 1.

Второй sed 's/,$//' используется для удаления конечного , в конце строки.

0 голосов
/ 04 июня 2018

Основная проблема с частью соответствия вашего регулярного выражения (@.*[^ ]) состоит в том, что .* соответствует почти всему остальному исходной строки после первой @ (довольно распространенная ошибка)и [^ ] соответствует последнему непробельному символу.

Если вы используете @\S+\s* в качестве части соответствия, тогда \S+ соответствует "непробельной" части (например, some_text/48183) и \s*после этого совпадает с дополнительными пробелами.

Эта замена дает foo,bar,xyz,, поэтому вам следует каким-то образом удалить последнюю запятую.

0 голосов
/ 04 июня 2018

После awk может помочь вам в этом.

awk 'BEGIN{OFS=","}{for(i=1;i<=NF;i++){sub(/@.*/,"",$i)}} 1'  Input_file

Решение 2-е: Взяв код из поста Виктора Стрибизью и немного изменив его, чтобы преобразовать егона один sed сейчас.

sed -E 's/([^@]+)@[^[:space:]]*[[:space:]]*/\1,/g;s/,$//'  Input_file
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...