Создание псевдонима для выражения xpath в xidel с помощью regex и bash - PullRequest
0 голосов
/ 16 февраля 2019

Если вы уже использовали Xidel, вам часто нужно будет найти узлы, которые имеют определенный класс.Чтобы сделать это проще, я хочу создать функцию has-class("class"), которая будет использоваться в качестве псевдонима для выражения:
contains(concat(" ", normalize-space(@class), " "), " class ").

Пример:

$ e-xidel.sh example.com '//article/p//img[has-class("wp-image")]'

e-xidel.sh содержит этот код:

#!/bin/bash

echo -e "$(tput setaf 2) Checking... $(tput sgr0)"

path=$1
expression=$2

# expression = '//article/p//img[has-class("wp-image")]'
# Regex to replace every * has-class("class") * by * contains(concat(" ", normalize-space(@class), " "), " class ") *
# ...
# ...
# expression = '//article/p//img[contains(concat(" ", normalize-space(@class), " "), " wp-image ")]'

xoutput=$(xidel $path --printed-node-format=html --output-declaration= -e "$expression")

echo -e "$(tput setaf 1) $xoutput $(tput sgr0)"

Ответы [ 2 ]

0 голосов
/ 20 августа 2019

contains(concat(" ", normalize-space(@class), " "), " class ")

Пример:

$ e-xidel.sh example.com '//article/p//img[has-class("wp-image")]'

Это не имеет смысла.

contains(concat(" ",normalize-space("wp-image")," ")," wp-image ")

будетпросто быть таким же, как

contains("wp-image","wp-image")

Если вы действительно хотите, чтобы логическое значение выводилось при сравнении значения атрибута class с литеральной строкой, то это ...

xidel -s example.com -e '//article/p//img/@class="wp-image"'

... вернет true или false.

Если wp-image является подстрокой значения атрибута class:

xidel -s example.com -e '//article/p//img/contains(@class,"wp-image")'
0 голосов
/ 18 февраля 2019

Вы можете использовать sed (версия GNU, не может гарантировать, что она будет работать с другими реализациями) для достижения ваших потребностей:

sed 's/has-class("\([^)]\+\)")/contains(concat(" ", normalize-space(@class), " "), " \1 ")/g'

Объяснение:

  • s/pattern/substitution/g: заменить часть, соответствующую шаблону, строкой substitution;Флаг g для замены всех частей строки (глобальная замена)
  • has-class("\([^)]\+\)"): часть, начинающаяся с has-class(", содержащая любой символ, кроме закрывающей скобки ([^)]) и заканчивающаясяна ").Экранированные круглые скобки, окружающие внутреннюю часть, захватывают часть и связывают ее с псевдонимом \1, поскольку это первая созданная группа захвата.
  • contains(concat(" ", normalize-space(@class), " "), " \1 "): замените сопоставленную часть этим текстом;\1 будет расширен содержимым связанной захваченной группы.

Ваш сценарий будет:

#!/bin/bash

function expand-has-class() {
    echo "$1" |
    sed 's/has-class("\([^)]\+\)")/contains(concat(" ", normalize-space(@class), " "), " \1 ")/g'
}

echo -e "$(tput setaf 2) Checking... $(tput sgr0)"

path=$1
expression="$(expand-has-class "$2")"

# expression = '//article/p//img[has-class("wp-image")]'
# Regex to replace every * has-class("class") * by * contains(concat(" ", normalize-space(@class), " "), " class ") *
# ...
# ...
# expression = '//article/p//img[contains(concat(" ", normalize-space(@class), " "), " wp-image ")]'

xoutput=$(xidel $path --printed-node-format=html --output-declaration= -e "$expression")

echo -e "$(tput setaf 1) $xoutput $(tput sgr0)"
...