Відповіді:
Ви можете використовувати -b
для зміщення байту, що є тим самим, що і положення для простого тексту (але не для UTF-8 або подібного).
$ echo "RAMSITALSKHMAN|1223333" | grep -aob '|'
14:|
У вищесказаному я використовую -a
перемикач, щоб сказати grep використовувати вхід як текст; необхідний під час роботи над бінарними файлами, і -o
перемикач виводить лише відповідні символи.
Якщо ви хочете лише позицію, ви можете використовувати grep, щоб витягнути лише позицію:
$ echo "RAMSITALSKHMAN|1223333" | grep -aob '|' | grep -oE '[0-9]+'
14
Якщо ви отримуєте дивний вихід, перевірте, чи у грепі не включені кольори. Ви можете відключити кольори, перейшовши --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 shell, ви можете використовувати суто вбудовані операції без необхідності нерестувати зовнішні процеси, такі як 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's це вже робить) ; оскільки для цього з expr
рішенням вам потрібно буде додати явний цикл (і відповідь Gnouc не легко адаптується, щоб це зробити взагалі, що я бачу), і (2) awk
рішення можуть бути адаптовані так, щоб повідомляти про всі Збігається в кожному рядку дещо простіше, ніж expr
рішення (насправді, це теж робить Авінаш Радж).
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))