Есть несколько способов сделать это.
ИМХО, лучше всего использовать awk
, что полезно при работе с полями.
Если вам нужно решение на основе grep
, я бы сделал:
grep -w '^5'
-w
указывает grep
на соответствие точному слову, поэтому это не будет соответствовать «52». «^» указывает grep искать 5 в начале строки, что не удастся, если есть, например. ведущие пробелы.
Решение awk
будет выглядеть так:
awk '$1 == 5'
Если вам нужно только имя пользователя, которое находится во втором столбце:
awk '$1 == 5 {print $2}'
Если вы ищете строку, а не числовое значение, заключите строку в двойные кавычки:
awk '$1 == "abc" {print $2}'
Я не думаю, что есть способ ограничить то, что передается оболочке с помощью модификатора e
; однако вы можете сделать что-то вроде этого:
$ sed -E ':a;s@(.*\[\[)([^][]* [^][]*)(\]\].*)@printf "%s%s%s" "\1" "$(printf "\2" | sed "s/ /-/g")" "\3"@e;ta' test.txt
abc [[foo]] xyz
abc [[foo-bar]] xyz
abc [[foo-bar-baz]] xyz [[something-else]]
Обратите внимание, что обработка множественных замен выполняется с помощью цикла -, и из-за жадности совпадения замены выполняются в обратном порядке.
Также обратите внимание, что e
использует /bin/sh
, который, скорее всего, не будет поддерживать <<<
перенаправление ввода (, следовательно, используется конвейерный эквивалентprintf "\2" | sed "s/ /-/g"
).
Если вы можете использовать perl, вы можете сделать что-то более близкое к вашему первоначальному замыслу, например.:
$ perl -pe 's/(?<=\[\[)(.*?)(?=\]\])/$1 =~ s: :-:rg/ge' test.txt
abc [[foo]] xyz
abc [[foo-bar]] xyz
abc [[foo-bar-baz]] xyz [[something-else]]
Так как perl предоставляет модификатор non -greedy ?
, он может обрабатывать несколько замен в строке более традиционным способом, используя флаг g
для внешней замены.
cat - <<\! > file
Abc [[ \ ]] def and a cup of
Ghi [[]] jkl
Mno [[ ]] pqr
abc [[" \' \\\"]] xyz
abc [[foo$$]] xyz [[a b c]] deal
abc [[foo bar]] xyz
abc [[foo bar baz]] xyz
abc [[foo $bar baz]] xyz [[FOO BAR VAZ]] $#
!
GNU sed
без использования модификатора /e
sed -Ee '
:loop
s/([[]{2}[^][]*) ([^]]*]])/\1-\2/
t loop
' file
Хотя это тривиально написать Posixly, но чтобы свести к минимуму обратную косую черту, которую мы используем с включенным расширенным режимом регулярных выражений, -E
. Цикл постепенно преобразует символ пробела/итерацию между парой `[[...]] ``. Цикл останавливается, когда он не может найти такие пробелы ни в одной паре. Затем печатается пространство шаблона и считывается следующая строка в пространство шаблона... полоскание... повторение, пока мы не увидим eof.
awk
разбивая каждую строку на строки [[
| ]]
. Мы можем себе это позволить, потому что симметрия ([[n]] )идет парами и в таком порядке. Никаких болтающихся [[ или ]]. Тогда каждое четное поле будет внутри [[ n ]] и должно быть обработано. awk -F '[[]{2}|]]' '
{
for (i=2; i<=NF; i+=2) {
gsub(/ /, "-", $i)
$i = "[[" $i "]]"
}
}1
' OFS= file
3. GNU sed
с использованием модификатора /e
.
sed -Ee "
s/'/&\"&\"&/g;tloop
:loop
s|(.*[[]{2})([^][]* [^]]*)(]].*)|v='\2';v=\${v// /-};printf '%s' '\1' \"\$v\" '\3'|e
t loop
" file
perl -F'(\[\[|]])' -lane 'my $i;
print map { ++$i%4 == 3 ? tr/ /-/r : $_ } @F;
' file
m='[^\n]'
sed -Ee "
s/[[]{2}|]]/&\n/g;T;h
:loop
s/^$m*\n($m*)\n.*/\1/
y/ /-/;G
s/^($m*)\n($m*)\n$m*\n/\2\1/
h
/\n/b loop
" file
Выход:
Abc [[-\--]] def
Ghi [[]] jkl
Mno [[-]] pqr
abc [["-\'-\\\"]] xyz
abc [[foo$$]] xyz [[a-b-c]] deal
abc [[foo-bar]] xyz
abc [[foo-bar-baz]] xyz
abc [[foo-$bar-baz]] xyz [[FOO-BAR-VAZ]] $#
Использование стандартаsed
:
$ sed -e ':again' -e 's/\(\[\[[^]]*\) \([^]]*\]\]\)/\1-\2/g' -e 't again' file
abc [[foo]] xyz
abc [[foo-bar]] xyz
abc [[foo-bar-baz]] xyz [[something-else]]
Это заменяет каждый символ пробела между [[
и ]]
тире. Это делается путем сопоставления [[
и ]]
, а в -между ними сопоставляется символ пробела, который может быть окружен какой-либо другой строкой. Совпадающая подстрока заменяется как есть, а пробел заменяется дефисом.
Если замена выполнена, команда t
возвращает сценарий к метке again
для другой замены. Это позаботится о пробелах, пропущенных в первый раз из-за перекрывающихся совпадений.
Так как указано, что каждый [[
всегда связан с]]
(предположительно в одной строке ), мы можем немного сократить команду:
sed -e ':again' -e 's/\(\[\[[^]]*\) /\1-/g' -e 't again' file
Это не ищет закрытия ]]
.