Grep का उपयोग करके किसी वर्ण की स्थिति कैसे प्राप्त करें?


11

मुझे grep कमांड का उपयोग करके स्ट्रिंग में एक वर्ण के पद की पहचान करने की आवश्यकता है।

उदाहरण के लिए, स्ट्रिंग है RAMSITALSKHMAN|1223333

grep -n '[^a-zA-Z0-9\$\~\%\#\^]'

मैं |दिए गए स्ट्रिंग में स्थिति कैसे पता करूँ ?


यह grep के साथ होना चाहिए?
ब्रायन

जवाबों:


29

आप -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=nevergrep को पास करके या grep कमांड को प्रीफ़िक्स करके रंगों को निष्क्रिय कर सकते हैं \(जो किसी भी उपनाम को निष्क्रिय कर देगा), जैसे:

$ echo "RAMSITALSKHMAN|1223333" | grep -aob '|' --color=never | \grep -oE '^[0-9]+'
14

एक स्ट्रिंग के लिए जो कई मैचों को लौटाती है, head -n1पहला मैच प्राप्त करने के लिए पाइप करें ।

ध्यान दें कि मैं उपरोक्त दोनों का उपयोग करता हूं, और ध्यान दें कि उत्तरार्द्ध काम नहीं करेगा अगर एक निष्पादन योग्य (स्क्रिप्ट या अन्यथा) के माध्यम से जीआरपी "अलियास" है, केवल उपनाम का उपयोग करते समय।


3
अब खोजें 2;)
इज़्काटा

धन्यवाद @ इज़कट, आप सही कह रहे हैं। मैंने अपनी पोस्ट को एक छोटा सा अपडेट किया है और लापता टोपी को जोड़ा है ^:)
runejuhl

1
किस संस्करण का आपने उपयोग किया? मुझे 0:|आउटपुट के रूप में मिलता है- क्योंकि 0 उस लाइन की शुरुआत की बाइट स्थिति है जहां |पाया जाता है।
एलेक्स

@ डेबियन खिंचाव से एलेक्स ग्नू ग्रीप grep (GNU grep) 2.27:। क्या आप शायद OS X का उपयोग कर रहे हैं?
रनजेहल

11

प्रयत्न:

printf '%s\n' 'RAMSITALSKHMAN|1223333.' | grep -o . | grep -n '|'

उत्पादन:

15:|

यह आपको सूचकांक आधारित -1 के साथ स्थिति देगा।


इसका काम नहीं कर रहा है :(
user82782

1
@ user82782: आपने क्या कमांड चलाया? तुम्हें पता है कि यह काम नहीं किया?
15

printf '%s\n' '|' | grep -o . | grep -n '|'प्रिंट 1, 0अपेक्षा के अनुरूप नहीं ।
l0b0

1
@ l0b0: ओपी यह नहीं बताता कि वह इंडेक्स बेस 0 या 1 चाहता था
cuonglm

मेरा बस यही मतलब है कि एक सॉफ्टवेयर डेवलपर क्या उम्मीद करेगा।
l0b0

8

यदि आप शेल का उपयोग कर रहे हैं , तो आप बाहरी प्रक्रियाओं जैसे कि या की आवश्यकता के बिना विशुद्ध रूप से निर्मित परिचालन का उपयोग कर सकते हैं :

$ str="RAMSITALSKHMAN|1223333"
$ tmp="${str%%|*}"
$ if [ "$tmp" != "$str" ]; then
> echo ${#tmp}
> fi
14
$ 

यह किसी स्ट्रिंग द्वारा अनुसरण की सभी घटनाओं को हटाने और एक अस्थायी चर में सहेजने के लिए एक पैरामीटर विस्तार का उपयोग करता है |। इसके बाद अस्थायी चर की लंबाई को मापने का एक सूचकांक है |

नोट ifअगर जाँच कर रहा है |मूल स्ट्रिंग में सभी पर मौजूद है। यदि यह नहीं होता है तो अस्थायी चर मूल के समान होगा।

नोट यह भी शून्य आधारित सूचकांक प्रदान |करता है जो आम तौर पर उपयोगी होता है जब बैंग के तारों को अनुक्रमित किया जाता है। हालाँकि यदि आपको एक-आधारित सूचकांक की आवश्यकता है, तो आप ऐसा कर सकते हैं:

$ echo $((${#tmp}+1))
15
$ 

1
शायद सबसे अच्छा जवाब, यह वाक्यविन्यास सुंदर और इतना तेज़ और प्रयोग करने में आसान है जब आप इसका अर्थ समझते हैं, लंबे समय तक कोर में रहते हैं
vdegenne

4

आप उन indexवर्णों में स्थिति वापस करने के लिए awk के फ़ंक्शन का उपयोग कर सकते हैं जहाँ मैच होता है:

echo "RAMSITALSKHMAN|1223333"|awk 'END{print index($0,"|")}'
15

यदि आप पर्ल के indexफ़ंक्शन का उपयोग करने में कोई आपत्ति नहीं करते हैं , तो यह शून्य, एक चरित्र की एक या अधिक घटनाओं की रिपोर्टिंग करता है:

echo "|abc|xyz|123456|zzz|" | \
perl -nle '$pos=-1;while (($off=index($_,"|",$pos))>=0) {print $off;$pos=$off+1}'

पठनीयता के लिए, केवल, पाइपलाइन को दो लाइनों में विभाजित किया गया है।

जब तक लक्ष्य वर्ण पाया जाता है, तब तक indexशून्य (0) पर आधारित सकारात्मक मान देता है। इसलिए, स्ट्रिंग "एबीसी | xyz | 123456 | zzz |" जब पार्स रिटर्न 0, 4, 8, 15 और 19 हो।


इस उपयोग के लिए, grep की तुलना में awk अधिक उपयोगी / आसान है।
15

यह केवल पहली स्थिति को प्रिंट करता है, जैसे स्ट्रिंग के साथ काम नहीं करेगाRAMSITALSKHMAN|1|223333
cuonglm

3

हम इसे "expr match" या "expr index" का उपयोग करके भी कर सकते हैं

expr मैच $ string $ substring जहाँ $ substring एक RE है।

echo `expr match "RAMSITALSKHMAN|1223333" '[A-Z]*.|'`

और ऊपर आपको स्थिति देगा क्योंकि यह मिलान किए गए विकल्प की लंबाई लौटाता है।

लेकिन खोज सूचकांक के लिए और अधिक विशिष्ट होना:

mystring="RAMSITALSKHMAN|122333"
echo `expr index "$mystring" '|'`

मुझे कहीं और टिप्पणी करने के लिए पर्याप्त प्रतिष्ठा नहीं है। मुझे व्यक्तिगत रूप से @Gnouc द्वारा दिया गया उत्तर पसंद आया। हालांकि, awk का उपयोग करना और इसे जटिल क्यों बनाना है जब हम 'expr' का उपयोग करके सरल काम कर सकते हैं
ब्लूफॉगी

@kingsdeb यह सिर्फ एक सुझाव है।
अविनाश राज

@kingsdeb: क्योंकि (1) awkसमाधान तुच्छ रूप से रिपोर्ट के लिए संशोधित किया जा सकता है इस जानकारी को किसी फ़ाइल की प्रत्येक पंक्ति पर (आपको बस इतना करना है END, जो कि JRFerguson के उत्तर से, और आवश्यक नहीं था, और अविनाश राज ने यह पहले ही कर दिया था) ; हालांकि expr, समाधान के साथ ऐसा करने के लिए , आपको एक स्पष्ट लूप जोड़ना होगा (और Gnouc का उत्तर आसानी से ऐसा करने के लिए अनुकूल नहीं है, जिसे मैं देख सकता हूं), और (2) awkसमाधान सभी को रिपोर्ट करने के लिए अनुकूलित किया जा सकता है exprसमाधान की तुलना में प्रत्येक पंक्ति में कुछ हद तक अधिक आसानी से मेल खाता है (वास्तव में, अविनाश राज पहले से ही ऐसा करता है)।
जी-मैन ने

आप echo `...`यहां क्यों इस्तेमाल करेंगे ?
स्टीफन चेजलस

यह केवल यहाँ आउटपुट दिखाने के लिए है
ब्लूफॉगी

2

एक और awk कमांड ,

$ echo 'RAMSITALSKHMAN|1223333'| awk 'BEGIN{ FS = "" }{for(i=1;i<=NF;i++){if($i=="|"){print i;}}}'
15

फ़ील्ड विभाजक को अशक्त स्ट्रिंग के रूप में सेट करके, awk अलग-अलग फ़ील्ड के रूप में रिकॉर्ड में अलग-अलग वर्ण को बदल देता है।


2

कुछ विकल्पों में शामिल हैं:

Gnouc के उत्तर के समान, लेकिन शेल के साथ:

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))
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.