Chci vyhledat řádky, které obsahují některý z následujících znaků:
:
/
/
?
#
[
]
@
!
$
&
"
(
)
*
+
,
;
=
%
odpověď
grep "[]:/?#@\!\$&"()*+,;=%[]"
V hranatém výrazu [...]
je velmi málo znaků “ speciální “ (pouze velmi malá podmnožina, jako ]
, -
a ^
a tři kombinace [=
, [:
a [.
). Při zahrnutí ]
do [...]
musí ]
být na prvním místě (pravděpodobně po ^
). Rozhodl jsem se dát ]
jako první a [
poslední pro symetrii.
Jediná další věc, kterou si musím pamatovat, je že řetězec s jednou uvozovkou nemůže obsahovat jedinou uvozovku, takže kolem výrazu používáme uvozovky. Jelikož používáme řetězec s dvojitou uvozovkou, shell se v něm bude hrabat, aby se věci mohly rozšířit. Z tohoto důvodu unikneme $
jako \$
, což způsobí, že shell dá doslovný $
to grep
a my unikneme !
jako \!
tak, jak to je historie rozšíření v bash
(pouze v interaktivních bash
skořápkách).
Chcete zahrnout zpětné lomítko do set, museli byste jej uniknout jako \\
, aby prostředí dalo jedno zpětné lomítko grep
. Také pokud chcete zahrnout backtick `
, musí také uniknout jako \`
, protože jinak spustí nahrazení příkazu.
Příkaz výše by extrahovalo jakýkoli řádek, který obsahoval alespoň jeden ze znaků v hranatém výrazu.
Použití řetězce s jednoduchou uvozovkou namísto řetězce s dvojitou uvozovkou, který obchází většinu obtěžování jaké znaky interpretuje shell:
grep "[]:/?#@!$&"""""()*+,;=%[]"
Zde je kromě pamětí ]
, je to, že jeden citovaný řetězec nemůže obsahovat jedinou citaci, takže místo toho použijeme zřetězení tří řetězců:
-
"[]:/?#@!$&"
-
"""
-
"()*+,;=%[]"
Jiným přístupem by bylo použití třídy znaků POSIX [[:punct:]]
. To odpovídá jednomu znaku ze sady !"#$%&"()*+,-./:;<=>?@[\]^_`{|}~
, což je větší sada než to, co je uvedeno v otázce (dále obsahuje "-.<>^_`{|}~
), ale jsou to všechny “ interpunkční znaky „, které POSIX definuje.
LC_ALL=C grep "[[:punct:]]"
Komentáře
Odpověď
Můžete použít [:punct:]
třídu znaků, pokud nevadí, že odpovídá i jiným interpunkčním a speciálním znakům:
grep "[[:punct:]]" file
Komentáře
-
punct
třída znaků (ne makro) odpovídá!"#$%&'()*+,-./:;<=>?@[\]^_
{|} ~ `v národním prostředí C, což je mírně velká sada znaků než co má uživatel, ale může to být dost dobré.
Odpověď
K vyhledání můžete použít plný regex speciální znaky v hranatých závorkách, pokud hledáte jeden znak, který je zvláštním znakem. Skvělým zdrojem pro nácvik, učení a kontrolu regulárních výrazů je regex101.com .
Používá regulární výrazy Perlu, které lze použít s GNU grep s možností -P
:
grep -P "(\:|\/|\?|\#|\@|\!|\\$|\&|\"|\(|\)|\*|\+|\,|\;|\=|\%|\[|\])" ^^^
Upozorňujeme, že potřebujete dva backsl popel před znakem dolaru, protože má v shellu zvláštní význam a první zpětné lomítko mu pro shell unikne. (S pouhým jedním zpětným lomítkem vpředu by shell odstranil zpětné lomítko, grep
by viděl neoznačený znak dolaru, což znamená konec řádku, a shodoval by se s jakýmkoli vstupním řádkem.)
Pokud váš terminál podporuje barvy, použijte také barvy,
grep --color=auto -P "(\:|\/|\?|\#|\@|\!|\\$|\&|\"|\(|\)|\*|\+|\,|\;|\=|\%|\[|\])"
Zde je vysvětlení mého regulárního výrazu z regex101.com
/(\:|\/|\?|\#|\@|\!|\$|\&|\"|\(|\)|\*|\+|\,|\;|\=|\%|\[|\])/gm 1st Capturing Group (\:|\/|\?|\#|\@|\!|\$|\&|\"|\(|\)|\*|\+|\,|\;|\=|\%|\[|\]) \: matches the character : literally (case sensitive) \/ matches the character / literally (case sensitive) \? matches the character ? literally (case sensitive) \# matches the character # literally (case sensitive) \@ matches the character @ literally (case sensitive) \! matches the character ! literally (case sensitive) \$ matches the character $ literally (case sensitive) \& matches the character & literally (case sensitive) \" matches the character " literally (case sensitive) \( matches the character ( literally (case sensitive) \) matches the character ) literally (case sensitive) \* matches the character * literally (case sensitive) \+ matches the character + literally (case sensitive) \, matches the character , literally (case sensitive) \; matches the character ; literally (case sensitive) \= matches the character = literally (case sensitive) \% matches the character % literally (case sensitive) \[ matches the character [ literally (case sensitive) \] matches the character ] literally (case sensitive)
Komentáře
- Ne, se standardním ERE ‚ nemůžete uniknout závěru
]
se zpětným lomítkem. zpětné lomítko není ve výrazech hranaté závorky zvláštní. Chcete-li mít]
uvnitř výrazu závorky, musí být nejprve:[]other]
, nikoli[ot\]her]
. To ‚ se liší od PCRE, které regex101 popisuje ve výchozím nastavení. - Fungovalo by to s
pcregrep
nebo GNUgrep -P
. A v jistém smyslu je chování Perlu přímočařejší: zpětné lomítko vždy dělá speciální znak normálním. - Opraveno na -P, omlouvám se, dostanu smíšené -E a -P
$
tam! Díky!bash: !\: event not found
.bash
! 🙂 Unikněte také!
… nebýtbash
uživatel, na který jsem zapomněl. Aktualizuji …"[\!]"
expanduje na[\!]
i když je povoleno rozšíření historie, shodovalo by se to i na zpětném lomítku. ‚ d potřebujete jednoduché uvozovky nebo použít\!
outsi počet citací.bash
,zsh
má také tuto nepříjemnou vlastnost zděděnou z csh. v csh také!
speciální uvnitř'...'
a také v případě, že není interaktivní. Vcsh
(na rozdíl od bash nebo zsh) by však použití"\!"
fungovalo zde (zpětné lomítko je odstraněno).