Yanıtlar:
-b
Basit metin konumu ile aynı olan bayt uzaklığını elde etmek için kullanabilirsiniz (ancak UTF-8 veya benzeri için değil).
$ echo "RAMSITALSKHMAN|1223333" | grep -aob '|'
14:|
Yukarıda, -a
grep'e girişi metin olarak kullanmasını söylemek için anahtarı kullanıyorum; ikili dosyalar üzerinde çalışırken ve -o
yalnızca eşleşen karakter (ler) in çıkış anahtarı kullanılır.
Yalnızca konumu istiyorsanız, grep komutunu yalnızca konumu çıkarmak için kullanabilirsiniz:
$ echo "RAMSITALSKHMAN|1223333" | grep -aob '|' | grep -oE '[0-9]+'
14
Tuhaf bir çıktı alırsanız, grep'in renklerin etkin olup olmadığını kontrol edin. --colors=never
Grep'e ileterek veya grep komutunun önüne bir ön ek uygulayarak \
(diğer adları devre dışı bırakacak) renkleri devre dışı bırakabilirsiniz, örneğin:
$ echo "RAMSITALSKHMAN|1223333" | grep -aob '|' --color=never | \grep -oE '^[0-9]+'
14
Birden çok eşleşme döndüren bir dize head -n1
için, ilk eşleşmeyi almak üzere geçiş yapın.
Her ikisini de yukarıda kullandığımı ve grep yalnızca bir takma ad (komut dosyası veya başka bir yolla), yalnızca takma adlar kullanarak "diğer adı" ise çalışmadığını unutmayın.
2
;)
^
0:|
0 satırın başlangıcına bayt pozisyonu olduğu için output-- olarak |
bulunmuştur.
grep (GNU grep) 2.27
. Belki OS X mi kullanıyorsunuz?
Deneyin:
printf '%s\n' 'RAMSITALSKHMAN|1223333.' | grep -o . | grep -n '|'
çıktı:
15:|
Bu size dizin tabanlı-1 olan konumu verecektir.
printf '%s\n' '|' | grep -o . | grep -n '|'
baskılar 1
, değil 0
beklendiği gibi.
Bash kabuğunu kullanıyorsanız, grep veya awk gibi harici süreçleri ortaya çıkarmaya gerek kalmadan tamamen yerleşik işlemleri kullanabilirsiniz :
$ str="RAMSITALSKHMAN|1223333"
$ tmp="${str%%|*}"
$ if [ "$tmp" != "$str" ]; then
> echo ${#tmp}
> fi
14
$
Bu, herhangi bir dizeyle aşağıdaki tüm oluşumları kaldırmak ve bunu geçici bir değişkene kaydetmek için bir parametre genişletmesi kullanır |
. Bu sadece endeksi elde etmek için geçici değişkenin uzunluğunu ölçmektir |
.
Dikkat if
edin,|
orijinal dizede hiç yoktur. Eğer değilse, geçici değişken orjinal ile aynı olacaktır.
Bu ayrıca |
, bash dizelerini dizine eklerken genellikle yararlı olan sıfır temelli dizini de sağlar . Ancak, tek tabanlı dizine ihtiyacınız varsa, bunu yapabilirsiniz:
$ echo $((${#tmp}+1))
15
$
Eşleşmenin index
gerçekleştiği karakterlerde konumu döndürmek için awk işlevini kullanabilirsiniz :
echo "RAMSITALSKHMAN|1223333"|awk 'END{print index($0,"|")}'
15
Perl index
işlevini kullanmanın bir sakıncası yoksa , bu, bir karakterin sıfır, bir veya daha fazla tekrarını bildirmeyi işler:
echo "|abc|xyz|123456|zzz|" | \
perl -nle '$pos=-1;while (($off=index($_,"|",$pos))>=0) {print $off;$pos=$off+1}'
Sadece okunabilirlik için, boru hattı iki hatta ayrılmıştır.
Hedef karakter bulunduğu sürece index
, sıfır (0) temelinde pozitif bir değer döndürür. Bu nedenle, "abc | xyz | 123456 | zzz |" dizesi ayrıştırıldığında 0, 4, 8, 15 ve 19 konumlarını döndürür.
RAMSITALSKHMAN|1|223333
Bunu "ifade eşleşmesi" veya "ifade dizini" kullanarak da yapabiliriz
expr $ string $ substring ile eşleşir; burada $ substring bir RE'dir.
echo `expr match "RAMSITALSKHMAN|1223333" '[A-Z]*.|'`
Ve yukarıda size pozisyonu verecektir, çünkü eşleşen alt dizenin uzunluğunu döndürür.
Ancak arama dizini için daha spesifik olmak gerekirse:
mystring="RAMSITALSKHMAN|122333"
echo `expr index "$mystring" '|'`
awk
çözümler bir dosyanın her satırında bu bilgileri rapor etmek için önemsiz bir şekilde değiştirilebilir (tek yapmanız END
gereken, gerçekten gerekli olmayan, JRFerguson'un cevabından kaldırmaktır ve Avinash Raj'ın zaten yaptığı) ; bununla birlikte, bunu expr
çözümle yapmak için, açık bir döngü eklemeniz gerekir (ve Gnouc'un cevabı bunu yapabilmek için kolayca uyarlanamaz, görebiliyorum) ve (2) awk
çözümler tüm raporları bildirmek için uyarlanabilir. her satırdaki expr
çözümden biraz daha kolay eşleşir (aslında, Avinash Raj'ın bunu zaten yaptığı gibi).
echo `...`
burada kullanasýn ki ?
$ echo 'RAMSITALSKHMAN|1223333'| awk 'BEGIN{ FS = "" }{for(i=1;i<=NF;i++){if($i=="|"){print i;}}}'
15
Alan ayırıcısını boş dize olarak ayarlayarak awk, kayıttaki tek tek karakteri ayrı alanlar olarak döndürür.
bazı alternatifler:
Gnouc'un cevabına benzer, ancak kabukla:
echo 'RAMSITALSKHMAN|1223333' |
tr -c \| \\n |
sh
sh: line 15: syntax error near unexpected token `|
sh: line 15: `|'
birden çok satıra sahip sed
ve dc
muhtemelen birden fazla satır içerebilir:
echo 'RAMSITALSKHMAN|1223333' |
sed 's/[^|]/1+/g;s/|/p/;1i0 1+' |dc
15
ile $IFS
...
IFS=\|; set -f; set -- ${0+RAMSITALSKHMAN|1223333}; echo $((${#1}+1))
Bu aynı zamanda kaç tane var olduğunu da söyleyecektir ...
echo $(($#-1))