2013-01-09 16 views
5

मेरे पास db.txt नामक एक टेक्स्ट फ़ाइल है। फ़ाइल से कुछ नमूना पंक्तियां इस तरह के रूप में चला जाता है:यूनिक्स बैश काटने और grep

हैरी पॉटर और जादूगर का पत्थर: J.K। राउलिंग: 21.95: 100: 200

हैरी पॉटर एंड द चैंबर ऑफ सीक्रेट्स: J.K। राउलिंग: 21.95: 150: 300

लोर्ड ऑफ द रिंग्स, अंगूठी की फैलोशिप: J.R.R। टोल्किन: 32.00: 500: 500

सिंहासन का एक खेल: जॉर्ज आर आर मार्टिन: 44.50: 300: 250

तब मेरी स्क्रिप्ट में

, मैं निम्नलिखित लाइनों है:

echo "Enter title:" 
read TITLE 

cut -d ":" -f 1 db.txt | grep -iw "$TITLE" | while read LINE 
do 
    STRING="`echo $LINE | cut -d ":" -f 1`," 
    STRING="$STRING `echo $LINE | cut -d ":" -f 2`, " 
    STRING=" \$$STRING`echo $LINE | cut -d ":" -f 3`," 
    STRING=" $STRING`echo $LINE | cut -d ":" -f 4`," 
    STRING=" $STRING`echo $LINE | cut -d ":" -f 5`" 
done 

है कटौती से एक विशिष्ट क्षेत्र को grep करने के लिए एक तरीका है और फिर पूर्ण लूप में जबकि लूप में पास?

उदाहरण के लिए, अगर मैं "हैरी पॉटर", में प्रवेश किया यह प्रदर्शित करना चाहिए:

हैरी पॉटर और जादूगर स्टोन, जे.के. राउलिंग, $ 21.95, 100, 200

हैरी पॉटर एंड द चैंबर ऑफ सीक्रेट्स, जे.के. राउलिंग, $ 21.95, 150, 300

+0

खोल में तर्ज पर एक पाश anormal है। सभी आदेश (grep, sed, cut, आदि ...) लाइनों पर पहले से ही एक लूप का उपयोग करें। – Zulu

उत्तर

5

आप cut के बिना यह कर सकते हैं, और grep बिना यदि मेल खाने वाले पार्टी की नियमित अभिव्यक्ति के साथ ठीक कर रहे हैं (या खोल पैटर्न बजाय मिलान का उपयोग कर सकते हैं)।

विचार लाइन द्वारा फ़ाइल लाइन को पढ़ने के लिए हो सकता है, तो एक सरणी में लाइन अलग हो गए। एक बार जब आप इसे प्राप्त कर लेंगे, तो तुलना करें और आउटपुट करें जो आप चाहते हैं।

यहाँ तकनीक का एक डेमो है:

#! /bin/bash 
echo "Title:" 
read title 

# shopt -s nocasematch   # if you want case-insensitive matching 

while read line ; do    # this read takes data from input.txt, see 
           # end of loop 
     IFS=: read -a parts <<< "$line" # this splits the line on ":" into 
             # an array called parts 

     if [[ ${parts[0]} =~ $title ]] ; then # regex matching 
       printf "%s -- %s\n" "${parts[1]}" "${parts[2]}" 
     fi 
done < input.txt 
+0

एक और चीज जो मैं जोड़ना चाहता हूं, आप केस-असंवेदनशीलता की जांच कैसे करते हैं और मैं पीछे की संख्या को प्रिंट करने के बारे में कैसे जा सकता हूं? मैंने% d की कोशिश की लेकिन संख्या शून्य के रूप में समाप्त हो गई। –

+0

केस-असंवेदनशील मिलान प्राप्त करने के लिए पोस्ट में 'shopt' पंक्ति को अनमोलमेंट करें। डॉलर की राशि के लिए '$%। 02f' आज़माएं, पूरे नंबरों के लिए'% d' आपके द्वारा प्रदान किए गए डेटा के साथ ठीक काम करता है। – Mat

+0

grep "हैरी पॉटर" db.txt इसे करना चाहिए! –

4

अगले कदम के ऊपर grep और cut से awk है।

awk -F: '/harry potter/ { sub(/^/,"$",$(NF-2)); print }' IGNORECASE=1 OFS=", " db.txt 

टेस्ट इनपुट:

Harry Potter and the Sorcerer's Stone:J.K. Rowling:21.95:100:200 
Harry Potter and the Chamber of Secrets:J.K. Rowling:21.95:150:300 
Lord of the Rings, The Fellowship of the Ring:J.R.R. Tolkien:32.00:500:500 
A Game of Thrones:George R.R. Martin:44.50:300:250 

टेस्ट उत्पादन: जब तक आप क्या करना चाहिए इस bash का उपयोग कर (? इस होमवर्क है), तो awk चीजें काफी आसान बना होगा

Harry Potter and the Sorcerer's Stone, J.K. Rowling, $21.95, 100, 200 
Harry Potter and the Chamber of Secrets, J.K. Rowling, $21.95, 150, 300 
2

ऐसा करने का सबसे आसान तरीका grep परिणामों को देखना है

#!/bin/bash 

read -p "Enter title: " TITLE 

FILENAME="db.txt" 
IFS=$'\n' 
for LINE in `grep -iw "Harry Potter" "$FILENAME"`; do 
    echo $LINE | awk 'BEGIN { FS = ":" } ; { print $1, $2, $3, $4, $5 }' 
done 

आईएफएस परिवर्तन के बजाय एक नई लाइन के लिए सीमांकक एक अंतरिक्ष और awk आदेश में एफएस में परिवर्तन करने के लिए सीमांकक परिवर्तन: खेतों

3
read -p "Enter title: " TITLE 
while IFS=: read title author price x y; do 
    if [[ ${title,,} == *${TITLE,,}* ]]; then 
     printf "%s, %s, $%s, %s, %s\n" "$title" "$author" "$price" "$x" "$y" 
    fi 
done < db.txt 

अगर आदेश में परीक्षण करने के लिए उपयोग की अनुमति एक साधारण ग्लोब-मैच करता है लेकिन मामला असंवेदनशील है, इसलिए यदि उपयोगकर्ता "कुम्हार" में प्रवेश करता है तो यह मेल खाता है।

या, विभाजक बदलने के लिए एसईडी का उपयोग करें:

read -p "Enter title: " TITLE 
sed '/'"$TITLE"'/I!d; s/:/, /g' db.txt 

, सभी लाइनों कि शीर्षक से मेल नहीं खाते हटाने के बाद फिर विभाजक को बदलने जिसका मतलब है।

1

आप sed उपयोग कर सकते हैं यदि यह एक समाधान होगा

read -p "Enter title: " TITLE 
    sed -n -e 's/^\([^:]\+:\)\{2\}/\0$/' -e 's/:/, /g' -e "/^$TITLE/Ip" db.txt 

लघु स्पष्टीकरण यह

-n tells sed not to print any lines 
-e 's/^\([^:]\+:\)\{2\}/\0$/' matches for the 2nd : and adds a $ after it 
-e 's/:/, /g' replaces all : with , and a following whitespace 
-e "/^$TITLE/Ip" tells sed to print all lines which start with $TITLE (that's the p) and I tells sed to match case-insensitive 
2

क्या करता है मैं जानता हूँ कि आप इसे निर्दिष्ट नहीं किया है, लेकिन awk शायद करने के लिए सबसे अच्छा उपकरण है इस काम के लिए उपयोग करें। यह कट, sed, और grep को एक सुविधाजनक और उपयोग में आसान टूल में जोड़ती है। खैर, सुविधाजनक उपकरण ...

awk समझने के लिए, आप कुछ चीजें समझना होगा:

  • Awk एक प्रोग्रामिंग भाषा है। यह तर्क और चर में बनाया गया है।
  • Awk प्रत्येक पंक्ति को पढ़ने वाले एक लूप को मानता है।
  • Awk प्रोग्राम घुंघराले ब्रेसिज़ से घिरा होना चाहिए।
  • इतना ही घुंघराले ब्रेसिज़, लेकिन Awk पार्स चर डॉलर चिह्न के साथ शुरू करते हैं। इसलिए, आपको खोलने के लिए अपने उद्धरण कार्यक्रमों को सिंगल कोट्स से घिरा रखना होगा।
  • Awk स्वचालित रूप से क्षेत्र विभाजक पर आधारित प्रत्येक पंक्ति पार्स करता है। डिफ़ॉल्ट फ़ील्ड विभाजक थोड़ी देर की जगह है, लेकिन आप इसे -f पैरामीटर के माध्यम से बदल सकते हैं।
  • प्रत्येक क्षेत्र एक विशेष चर हो जाता है। पहले क्षेत्र $1 है, अगले क्षेत्र $2 है, आदि पूरी पंक्ति $0 है।

    awk -F: '{ print "I read " $4 " pages " out of " $5 " of " $1 " by " $2 "." }' $file 
    

    बस Awk और कैसे की programability पर जोर देना चाहता था:

    awk -F: '{ 
        title = $1 
        author = $2 
        price = $3 
        pages_read_until_i_got_bored=$4 
        pages = $5 
        print "I read " pages_read_until_i_gob_bored "pages out of " $pages " pages of " $title " by " $author "." 
    }' $file 
    
    बेशक

    , पूरी बात भी एक लाइन हो सकता है:

यहाँ अपने Awk बयान है इसका उपयोग इस प्रकार के पार्सिंग करने के लिए किया जा सकता है।

अपने सवाल यह है कि इस जानकारी दर्ज करें और यह वातावरण चर में डाल रहा है, Glenn Jackman's जवाब सबसे अच्छा है।