Ответы:
Вы можете использовать -b
для получения байтового смещения, которое совпадает с позицией для простого текста (но не для UTF-8 или аналогичного).
$ echo "RAMSITALSKHMAN|1223333" | grep -aob '|'
14:|
Выше я использую -a
переключатель, чтобы сказать grep использовать ввод как текст; необходимо при работе с двоичными файлами, и -o
переключатель должен выводить только совпадающие символы.
Если вам нужна только позиция, вы можете использовать grep для извлечения только позиции:
$ echo "RAMSITALSKHMAN|1223333" | grep -aob '|' | grep -oE '[0-9]+'
14
Если вы получаете странный вывод, проверьте, включены ли в grep цвета. Вы можете отключить цвета, передав --colors=never
команду grep или добавив префикс команды grep с помощью \
(который отключит любые псевдонимы), например:
$ echo "RAMSITALSKHMAN|1223333" | grep -aob '|' --color=never | \grep -oE '^[0-9]+'
14
Для строки, которая возвращает несколько совпадений, проследуйте, head -n1
чтобы получить первое совпадение.
Обратите внимание, что я использую как в приведенном выше, и обратите внимание, что последний не будет работать, если grep «псевдоним» через исполняемый файл (сценарий или иным образом), только при использовании псевдонимов.
2
;)
^
:)
0:|
качестве вывода-- потому что 0 это позиция байта начала строки, где |
находится.
grep (GNU grep) 2.27
. Возможно, вы используете OS X?
Пытаться:
printf '%s\n' 'RAMSITALSKHMAN|1223333.' | grep -o . | grep -n '|'
вывод:
15:|
Это даст вам позицию с индексом на основе-1.
printf '%s\n' '|' | grep -o . | grep -n '|'
печатает 1
не так, 0
как ожидалось.
Если вы используете оболочку bash , вы можете использовать чисто встроенные операции без необходимости порождения внешних процессов, таких как grep или awk :
$ str="RAMSITALSKHMAN|1223333"
$ tmp="${str%%|*}"
$ if [ "$tmp" != "$str" ]; then
> echo ${#tmp}
> fi
14
$
При этом используется расширение параметра, чтобы удалить все вхождения |
после любой строки и сохранить его во временной переменной. Тогда нужно просто измерить длину временной переменной, чтобы получить индекс |
.
Обратите внимание, что if
проверяется, |
существует ли вообще исходная строка. Если этого не произойдет, тогда временная переменная будет такой же, как и оригинальная.
Также обратите внимание, что это обеспечивает нулевой индекс, |
который обычно полезен при индексации строк bash. Однако если вам требуется индекс на основе одного, то вы можете сделать это:
$ echo $((${#tmp}+1))
15
$
Вы можете использовать index
функцию awk для возврата позиции в символах, где происходит совпадение:
echo "RAMSITALSKHMAN|1223333"|awk 'END{print index($0,"|")}'
15
Если вы не возражаете против использования функции Perl index
, это обрабатывает сообщение об отсутствии, одном или нескольких вхождениях символа:
echo "|abc|xyz|123456|zzz|" | \
perl -nle '$pos=-1;while (($off=index($_,"|",$pos))>=0) {print $off;$pos=$off+1}'
Только для удобства чтения конвейер разделен на две строки.
Пока целевой символ найден, index
возвращает положительное значение, основанное на нуле (0). Следовательно, строка «abc | xyz | 123456 | zzz |» при разборе возвращает позиции 0, 4, 8, 15 и 19.
RAMSITALSKHMAN|1|223333
Мы также можем сделать это, используя «expr match» или «expr index»
expr соответствует $ string $ substring, где $ substring является RE.
echo `expr match "RAMSITALSKHMAN|1223333" '[A-Z]*.|'`
И выше даст вам позицию, потому что он возвращает длину совпадающей подстроки.
Но чтобы быть более конкретным для поиска индекса:
mystring="RAMSITALSKHMAN|122333"
echo `expr index "$mystring" '|'`
awk
решения могут быть тривиально изменены для сообщения этой информации в каждой строке файла (все, что вам нужно сделать, это удалить то END
, что никогда не было действительно необходимым, из ответа JRFerguson, а Avinash Raj уже делает это) ; тогда как, чтобы сделать это с expr
решением, вам нужно было бы добавить явный цикл (а ответ Gnouc совсем не так легко сделать, что я вижу), и (2) awk
решения могут быть адаптированы так, чтобы сообщать обо всех совпадения в каждой строке несколько проще, чем expr
решение (на самом деле, Avinash Raj's тоже это делает).
echo `...`
здесь?
$ echo 'RAMSITALSKHMAN|1223333'| awk 'BEGIN{ FS = "" }{for(i=1;i<=NF;i++){if($i=="|"){print i;}}}'
15
Устанавливая разделитель полей как пустую строку, awk превращает отдельный символ в записи в отдельные поля.
некоторые альтернативы включают в себя:
аналогично ответу Гнука, но с оболочкой:
echo 'RAMSITALSKHMAN|1223333' |
tr -c \| \\n |
sh
sh: line 15: syntax error near unexpected token `|
sh: line 15: `|'
с sed
и dc
возможно охватывая несколько строк:
echo 'RAMSITALSKHMAN|1223333' |
sed 's/[^|]/1+/g;s/|/p/;1i0 1+' |dc
15
с $IFS
...
IFS=\|; set -f; set -- ${0+RAMSITALSKHMAN|1223333}; echo $((${#1}+1))
Это будет также сказать вам , как много есть , как ...
echo $(($#-1))