क्यों है `sed expr1 | sed expr2` को `sed -e expr1 -e expr2` के लिए अलग


10

मैं उन idसमूहों के अधिक पठनीय लाइन-दर-सूची सूची प्रदान करने के लिए आउटपुट को विभाजित कर रहा था जिनमें से एक उपयोगकर्ता एक सदस्य है:

id roaima | sed 's/,/\n\t/g'
uid=1001(roaima) gid=1001(roaima) groups=1001(roaima)
    24(cdrom)
    25(floppy)
    ...
    822413650 (international (uk) location)

मैं समूह संख्या को उसके ब्रैकेट नाम से अलग करना चाहता था इसलिए मैंने इस तरह से अभिव्यक्ति को बढ़ाया

id roaima | sed -e 's/,/\n\t/g' -e '2,$s/(/ (/'

हालाँकि, इसने अभिनय नहीं किया जैसा कि मुझे शुरू में उम्मीद थी। दूसरी अभिव्यक्ति का कोई असर नहीं हुआ।

इसके बजाय, मैं जो परिणाम चाहता था, उसे पाने के लिए मुझे दो अलग-अलग sedकमांड चलाने की जरूरत थी , जैसे:

id roaima | sed -e 's/,/\n\t/g' | sed '2,$s/(/ (/'
uid=1001(roaima) gid=1001(roaima) groups=1001(roaima)
    24 (cdrom)
    25 (floppy)
    ...
    822413650 (international (uk) location)

मुझे sedकई निर्देशों के साथ एक के बजाय एक पाइप में दो कमांड की आवश्यकता क्यों है ? या अगर मैं एक के साथ ऐसा कर सकता हूं sed, तो मैं ऐसा कैसे करूंगा?

मैं विशेष रूप से यूआईडी / जीआईडी ​​मूल्य और हर एकल आइटम के लिए इसके ब्रैकेटेड नाम (पहली पंक्ति पर यूआईडी और जीआईडी ​​सहित) के बीच एकल स्थान रखना चाहता हूं, लेकिन यह चेतावनी है कि मेरे वास्तविक डेटा में मैं समूह बना सकता हूं उनके नाम में कोष्ठक होते हैं और मैं उन नामों को नहीं चाहता जो स्वयं मंगवाए थे।

जवाबों:


14

sed, की तरह awkया cutया perl -neप्रत्येक पंक्ति पर काम करता है व्यक्तिगत रूप से एक के बाद एक।

sed -e code1 -e code2

वास्तव में निम्नानुसार चलाया जाता है:

while(patternspace = getline()) {
  linenumber++
  code1
  code2
} continue {print patternspace}

यदि आपका कोड 2 है 2,$ s/foo/bar/, तो:

if (linenumber >= 2) sub(/foo/, "bar", patternspace)

जैसा कि आपके इनपुट में केवल एक पंक्ति है, sub()कभी नहीं चलाया जाएगा।

पैटर्न में अंतरिक्ष में newline वर्ण सम्मिलित code1करने से linenumberवृद्धि नहीं होती है।

इसके बजाय, आपके पास इनपुट के पहले और एकमात्र लाइन को संसाधित करते समय इसमें कई लाइनों के साथ एक पैटर्न स्थान है । यदि आप दूसरी लाइन और उस मल्टी-लाइन पैटर्न स्पेस में संशोधन करना चाहते हैं, तो आपको कुछ ऐसा करने की आवश्यकता है:

s/\(\n[^(]*\)(/\1 (/g

हालांकि यहाँ निश्चित रूप से, आप एक ही बार में दो ऑपरेशन कर सकते हैं:

id | sed 's/,\([^(]*\)(/\n\t\1 (/g'

awk, और perl -n / p, प्रत्येक रिकॉर्ड पर काम करता है जो एक पंक्ति में चूक करता है लेकिन बदला जा सकता है; इस मामले में -vRS=,या -054मदद कर सकता है।
dave_thompson_085

5

यदि आपके पास GNU sed है, तो आप उपयोग कर सकते हैं

id username | sed 's/(/ (/4g; s/,/\n\t/g'

जो 4 वें और बाद में खुले कोष्ठक से पहले एक स्थान जोड़ता है, फिर कॉमा को बदल देता है।


1
यह दिलचस्प लग रहा है। दुर्भाग्यवश यह समूहनामों को भी प्रभावित करता है जिनमें मेरे उदाहरण के रूप में ब्रैकेट शामिल हैं international (uk) location, नाम में एक अवांछित स्थान डालकर।
रोज़ा

फिर उपयोग करें s/\([[:digit:]]\+\)(/\1 (/4gजो केवल कोष्ठक से पहले अंक होने पर एक स्थान जोड़ देगा।
ग्लेन जैकमैन

1

@ स्टीफन-चेज़लस ने जो कहा वह सच है, लेकिन आप हमेशा पहले स्थान जोड़ सकते हैं और इस तरह से लाइनों में विभाजित कर सकते हैं:

sed -e 's:\([,=][0-9]*\):\1 :g' -e 's:,:\n\t:g'

या एक सिंगल सेड स्क्रिप्ट में (बिना -e):

sed 's:\([,=][0-9]*\):\1 :g; s:,:\n\t:g'

हम सामान्य /रूप से कमांड कमांड के विभाजक के रूप में " " का उपयोग करते हैं , लेकिन यह किसी भी वर्ण को स्वीकार करता है, इसलिए कभी-कभी " :" जैसे संयोजनों से बचने के लिए " " जैसे अन्य चार्ट का उपयोग करना आसान होता है /\

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