बैश स्क्रिप्ट में टैब डेलीनेटेड फाइल के माध्यम से लूप


18

यहाँ मेरे पास अभी तक क्या है:

#!/bin/bash
while read line; do
        DB=$(echo $line | cut -f1)
        USER=$(echo $line | cut -f2)
        PASS=$(echo $line | cut -f3)
        echo DB=$DB USER=$USER PASS=$PASS
done < users.txt

और इनपुट फ़ाइल का एक नमूना:

drupal_1    drupal1 tmmjXSWL
drupal_2    drupal2 FHiJSYHM
drupal_3    drupal3 b7bFNj06
drupal_4    drupal4 0AaV62EL

और स्क्रिप्ट से आउटपुट:

DB=drupal_1 drupal1 tmmjXSWL USER=drupal_1 drupal1 tmmjXSWL PASS=drupal_1 drupal1 tmmjXSWL
DB=drupal_2 drupal2 FHiJSYHM USER=drupal_2 drupal2 FHiJSYHM PASS=drupal_2 drupal2 FHiJSYHM
DB=drupal_3 drupal3 b7bFNj06 USER=drupal_3 drupal3 b7bFNj06 PASS=drupal_3 drupal3 b7bFNj06

किसी कारण से, प्रत्येक चर पूरी रेखा पर सेट है। जब मैं echo users.txt | cut -f1कमांड लाइन पर उपयोग करता हूं , तो यह टोकन को ठीक तरह से लौटाता है।

जवाबों:


6

इस बारे में कैसा है?

$ awk '{print "DB="$1"\tUSER="$2"\tPASS="$3}' users.txt
DB=drupal_1 USER=drupal1    PASS=tmmjXSWL
DB=drupal_2 USER=drupal2    PASS=FHiJSYHM
DB=drupal_3 USER=drupal3    PASS=b7bFNj06
DB=drupal_4 USER=drupal4    PASS=0AaV62EL

अगर आप को हल करने के लिए कोई समस्या है, तो मैं नहीं बता सकता या एक अधिक सैद्धांतिक मुद्दे के बारे में सोच रहा हूँ।


धन्यवाद, वह काम करता है। मैं जिस कक्षा में पढ़ा रहा हूं, उसके लिए सर्वर पर 40+ ड्रुपल इंस्टॉलेशन बनाने के लिए एक स्क्रिप्ट लिखने की कोशिश कर रहा हूं। मेरे पास DBs और फ़ाइलों को सेटअप करने के लिए स्क्रिप्ट है, यह स्क्रिप्ट का एक टुकड़ा है जो इसे सभी को एक साथ रखेगा। मेरे कोड के साथ समस्या यह थी कि $ लाइन रिक्त स्थान में बदल गई क्योंकि यह पार्स हो गया था। $(echo $line | cut -d" " -f1)भी काम करता है।
मोर्टोना 42

मेरे लिए विफल रहता है अगर किसी भी क्षेत्र में रिक्त स्थान हैं
v01pe

21

समस्या कमांड में है echo $line। चूंकि आस-पास कोई उद्धरण नहीं है $line, इसलिए शेल उस पर विभाजित शब्द निष्पादित करता है, फिर प्रत्येक शब्द को ग्लोबिंग पैटर्न के रूप में व्याख्या करता है। इसके साथ प्रयास करें

a='*.txt foo'
ls $a

आपके मामले में, टैब अलग-अलग शब्द बनाते हैं, जो तब अलग-अलग तर्क बन जाते हैं echoechoआदेश प्रिंट अपने तर्कों एक रिक्ति से अलग कर दिया। तो cutटैब-सीमांकित फ़ील्ड के बजाय अंतरिक्ष-सीमांकित फ़ील्ड प्राप्त करना समाप्त होता है।

हमेशा चर प्रतिस्थापन $fooऔर कमांड प्रतिस्थापन के आसपास दोहरे उद्धरण चिह्नों$(foo) (जब तक आप यह नहीं समझते कि आपको उन्हें छोड़ने की आवश्यकता क्यों है और ऐसा करने के लिए क्यों ठीक है)। echo "$line"यहाँ काम करेगा, लेकिन यह एक जटिल तरीका है कि आप क्या प्रस्ताव देते हैं।

शेल में पार्सिंग के अपने दृष्टिकोण को ध्यान में रखते हुए, आप readकमांड पार्स इनपुट को खेतों में बना सकते हैं ।

while read DB USER PASS; do
  echo "DB=$DB USER=$USER PASS=$PASS"
done <users.txt

readIFSचर के मान से वर्णों के द्वारा अलग किए गए फ़ील्ड को विभाजित करता है , जिसमें डिफ़ॉल्ट रूप से एक स्थान और एक टैब (साथ ही एक नई रेखा, जो लाइन के अंदर नहीं हो सकती है) शामिल हैं। केवल टैब पर विभाजित करने के लिए, IFSपहले एक टैब पर सेट करें। ध्यान दें कि अग्रणी और अनुगामी टैब को अनदेखा किया जाता है और लगातार टैब एक ही के रूप में गिने जाते हैं।

read\एक विशेष चरित्र के रूप में व्यवहार करता है : एक बैकलाइन को एक नई पंक्ति द्वारा अनदेखा किया जाता है; \\सिंगल बैकस्लैश बन जाता है। यदि आप इस व्यवहार से बचना चाहते हैं, तो -rविकल्प पास करें ।


15
+1। IFS को बैश में एक टैब चार सेट करने के लिए:IFS=$'\t'
ग्लेन जैकमैन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.