Regex: найти элементы независимо от порядка - PullRequest
2 голосов
/ 01 июля 2019

Если у меня есть строка:

гео: FR, хост: www.example.com

(На самом деле строка более сложная и имеет больше полей.)

И я хочу извлечь значение "geo" и значение "host", я столкнулся с проблемой при изменении порядка ключей, как показано ниже:

хост: www.example.com, гео: FR

Я пробовал эту строку:

sed 's/.\*geo:\([^ ]*\).\*host:\([^ ]*\).*/\1,\2/'

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

Ответы [ 3 ]

2 голосов
/ 01 июля 2019

Всякий раз, когда у вас есть пары тег / имя к значению на входе, я считаю наилучшим (самый простой, самый простой, самый надежный, самый простой для улучшения и т. Д.) Сначала создать массив, содержащий это отображение (f[] ниже) и тогда вы можете просто получить доступ к значениям по их тегам:

$ cat file
geo:FR, host:www.example.com
host:www.example.com, geo:FR
foo:bar, host:www.example.com, stuff:nonsense, badgeo:uhoh, geo:FR, nastygeo:wahwahwah

$ cat tst.awk
BEGIN { FS=":|, *"; OFS="," }
{
    for (i=1; i<=NF; i+=2) {
        f[$i] = $(i+1)
    }
    print f["geo"], f["host"]
}

$ awk -f tst.awk file
FR,www.example.com
FR,www.example.com
FR,www.example.com

Вышеописанное будет работать с использованием любого awk в любой оболочке на каждом компьютере UNIX.

2 голосов
/ 01 июля 2019

Я предлагаю извлечь каждый нужный вам текст с помощью отдельной команды sed:

s="geo:FR, host:www.example.com"
host="$(sed -n 's/.*host:\([^[:space:],]*\).*/\1/p'  <<< "$s")"
geo="$(sed -n 's/.*geo:\([^[:space:],]*\).*/\1/p'  <<< "$s")"

См. онлайн-демонстрацию , echo "$host and $geo" отпечатков

www.example.com and FR

дляоба входа.

Подробности

  • -n подавляет линейный вывод, а p печатает совпадения
  • .* - соответствует любому0+ обозначает последнюю ...
  • host: - host: подстроку, а затем
  • \([^[:space:],]*\) - захватывает в группу 1 любые 0 или более символов, кроме пробелов и запятой
  • .* - остаток строки.

Результатом является только содержимое группы 1 (см. \1 в шаблоне замены).

0 голосов
/ 01 июля 2019

Здесь я использовал GNU Awk для преобразования пар key:value с разделителями в правильное назначение оболочки. С Bash вы можете загрузить эти назначения в вашу текущую оболочку, используя <(process substitution):

# source the file descriptor generated by proc sub
. < <(

  # use comma-space as field separator, literal apostrophe as variable q
  awk -F', ' -vq=\' '

    # change every foo:bar in line to foo='bar' on its own line
    {for(f=1;f<=NF;f++) print gensub(/:(.*)/, "=" q "\\1" q, 1, $f)}

  # use here-string to load text; remove everything but first quote to use standard input
  ' <<< 'host:www.example.com, geo:FR'
)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...