Это очень распространенная проблема, возникающая из-за непонимания работы :nth-child()
и :nth-of-type()
. К сожалению, в настоящее время нет решения на основе селектора, поскольку селектор не обеспечивает способ сопоставления n-го дочернего элемента, который соответствует произвольному селектору на основе шаблона, такого как нечетные, четные или любые an+b
, где a != 1
и b != 0
.
:nth-child()
псевдокласса подсчитывает элементы среди всех всех их братьев и сестер под одним и тем же родителем. Он не учитывает только братьев и сестер, которые соответствуют остальной части селектора. Аналогично, псевдо-класс :nth-of-type()
считает, что siblings используют один и тот же тип элемента, который относится к имени тега в HTML, а не к остальной части селектора.
Это также означает, что если все дочерние элементы одного и того же родителя имеют один и тот же тип элемента, например, в случае тела таблицы, единственными дочерними элементами которого являются tr
или элемент списка, единственными дочерними элементами которого являются li
, тогда :nth-child()
и :nth-of-type()
будут вести себя одинаково, т. е. для каждого значения an+b
, :nth-child(an+b)
и :nth-of-type(an+b)
будут соответствовать одному и тому же набору элементов.
На самом деле все простые селектора в данном соединении селектор, включая псевдоклассы, такие как :nth-child()
и :not()
, работают независимо друг от друга , вместо того, чтобы смотреть на подмножество элементов, которые сопоставляются остальными селектора.
Это также подразумевает, что нет понятия порядка среди простых селекторов в каждом отдельном селекторе 1, что означает, например, следующие два селектора эквивалентны:
[f 1]
При переводе на английский язык оба означают:
Выберите любой элемент
tr
, который соответствует всем следующим независимым условиям:blockquote>
- нечетный номер родительского родителя;
- имеет класс «строка»; и
- является потомком элемента
table
, который имеет класс «myClass».(вы заметите, что мое использование неупорядоченный список здесь, просто для того, чтобы управлять точкой.)
Поскольку в настоящее время нет чистого решения CSS, вам придется использовать скрипт для фильтрации элементов и соответственно применять стили или дополнительные имена классов. Например, следующее обходное решение, использующее jQuery (предполагается, что в таблице есть только одна группа строк, заполненная элементами
tr
):$('table.myClass').each(function() { // Note that, confusingly, jQuery's filter pseudos are 0-indexed // while CSS :nth-child() is 1-indexed $('tr.row:even').addClass('odd'); });
С соответствующим CSS:
table.myClass tr.row.odd { ... }
Если вы используете автоматические инструменты тестирования, такие как Selenium или обрабатываете HTML с помощью таких инструментов, как lxml, многие из этих инструментов позволяют XPath в качестве альтернативы:
//table[contains(concat(' ', @class, ' '), ' myClass ')]//tr[contains(concat(' ', @class, ' '), ' row ')][position() mod 2)=1]
Другие решения, использующие разные технологии, оставил в качестве упражнения читателю; это всего лишь краткий, надуманный пример для иллюстрации.
Для чего это стоит, есть предложение для расширения к
:nth-child()
нотации , которое должно быть добавлено к Селекторы уровня 4 для конкретной цели выбора каждого n-го дочернего элемента, соответствующего данному селектору.2Селектор, в котором для фильтрации совпадений предоставляется в качестве аргумента
:nth-child()
, снова из-за того, как селектора работают независимо от друг друга в последовательности, продиктованной существующим синтаксисом селектора. Итак, в вашем случае это будет выглядеть так:table.myClass tr:nth-child(odd of .row)
(Проницательный читатель сразу заметит, что это должно быть
:nth-child(odd of tr.row)
вместо этого, поскольку простые селекторtr
и:nth-child()
работают независимо друг от друга. Это одна из проблем с функциональными псевдоклассами, которые принимают селекторы, банку червей, которую я предпочитаю не открывать посреди этого ответа. Вместо этого я собираюсь перейти к предположению что большинство сайтов не будут иметь каких-либо других элементов, кроме элементовtr
, как братьев и сестер друг друга в теле таблицы, что сделает любой вариант функционально эквивалентным.)Конечно, будучи новым предложением в новая спецификация, это, вероятно, не увидит реализацию до нескольких лет в будущем. В то же время вам придется придерживаться сценария, как указано выше.
1 Если вы укажете тип или универсальный селектор, он должен быть первым. Однако это не меняет того, как работают селекторы. это не что иное, как синтаксический приступ.
2 Первоначально это было предложено как
:nth-match()
, однако, поскольку оно по-прежнему считает элемент относительным только для его братьев и сестер, а не для каждого другого элемента, который соответствует данному селектору, он с тех пор, как с 2014 года был перепрофилирован как расширение существующего:nth-child()
.
Нет. Расширение происходит до того, как команда будет запущена. Вы можете только отключить glob перед запуском команды или путем цитирования звезды.
$ # quote it
$ foo '*'
$ # or escape it
$ foo \*
$ # or disable the glob (noglob)
$ set -f
$ foo *
Остерегайтесь: если нет имен, соответствующих маске, bash передает аргумент as-is без расширения!
Proof (pa.py - очень простой скрипт, который просто печатает свои аргументы):
$ ls
f1.cc f2.cc pa.py
$ ./pa.py *.cc
['./pa.py', 'f1.cc', 'f2.cc']
$ ./pa.py *.cpp
['./pa.py', '*.cpp']
set -o nullglob
или shopt -s failglob
, и это поведение изменится (двумя разными способами).
– Charles Duffy
1 December 2015 в 01:22
Расширение выполняется оболочкой перед запуском вашей программы. Ваша программа не имеет понятия, произошло ли расширение или нет.
set -o noglob
отключит расширение в вызывающей оболочке, но вам нужно будет сделать это перед , вы вызываете свою программу.
Альтернатива процитировать ваши аргументы, например
foo "*"
set -o noglob
для отключения расширения подстановочных знаков.
– Wirawan Purwanto
4 March 2016 в 22:31
Хотя верно, что сама команда не может отключить глобус, пользователь может сказать оболочке Unix, чтобы не глотать определенную команду. Обычно это делается путем редактирования файлов конфигурации оболочки. Предполагая, что команда foo
может быть найдена по пути к команде, в соответствующий файл конфигурации необходимо добавить следующее:
Для оболочек sh, bash и ksh:
alias foo='set -f;foo';foo(){ command foo "$@";set +f;}
Для оболочек csh и tcsh:
alias foo 'set noglob;\foo \!*;unset noglob'
Для оболочки zsh:
alias foo='noglob foo'
Путь к командной строке не нужно использовать. Скажем, команда foo хранится в каталоге ~ / bin, а затем следующее:
Для оболочек sh, bash и ksh:
alias foo='set -f;foo';foo(){ ~/bin/foo "$@";set +f;}
Для csh и tcsh shells:
alias foo 'set noglob;$home/bin/foo \!*;unset noglob'
Для оболочки zsh:
alias foo='noglob ~/bin/foo'
Все вышеперечисленное было протестировано с использованием OSX 10.9.2 от Apple. Примечание. При копировании вышеуказанного кода будьте осторожны при удалении любых пробелов. Они могут быть значительными.
Пользователь geira указал, что в случае оболочки bash
alias foo='set -f;foo';foo(){ ~/bin/foo "$@";set +f;}
можно заменить на
reset_expansion(){ CMD="$1";shift;$CMD "$@";set +f;}
alias foo='set -f;reset_expansion ~/bin/foo'
, что устраняет необходимость в функции foo.
Некоторые веб-сайты, используемые для создания этого документа:
Нет. Оболочка типа Bourne всегда выполняет globbing , когда это необходимо, перед выполнением команды. Пользователь должен указывать или избегать аргументов, чтобы предотвратить глобус, например foo \*
; фактическая выполняемая программа не может указывать предпочтения.
setopt
, но set -o noglob
.
– Anne van Rossum
4 December 2013 в 14:57
pwd
,echo *
является просто*
– sam boosalis 1 April 2014 в 00:48nullglob
отключена, слово остается неизменным. Если параметрnullglob
установлен, и совпадений не найдено, слово удаляется. & Quot; – Chris Middleton 6 February 2015 в 19:05