प्रत्येक पंक्ति के लिए स्ट्रिंग प्रस्तुत करने की कमान?


36

कुछ इस तरह से खोज रहे हैं? कोई विचार?

cmd | prepend "[ERRORS] "

[ERROR] line1 text
[ERROR] line2 text
[ERROR] line3 text
... etc

क्या bash function / script में सभी कमांड के लिए इसे सेट करने का कोई तरीका है?
अलेक्जेंडर मिल्स

जवाबों:


39
cmd | while read line; do echo "[ERROR] $line"; done

केवल बैश बिल्डरों का उपयोग करने का लाभ है, इसलिए कम प्रक्रियाएं बनाई जाएंगी / नष्ट हो जाएंगी, इसलिए यह awk या sed की तुलना में तेजी से स्पर्श होना चाहिए।

@tzrik बताते हैं कि यह एक अच्छा बैश फंक्शन भी कर सकता है। इसे परिभाषित करना:

function prepend() { while read line; do echo "${1}${line}"; done; }

इसे उपयोग करने की अनुमति देगा:

cmd | prepend "[ERROR] "

4
यह वास्तव में केवल एक द्वारा की जाने वाली प्रक्रिया को कम करता है। (लेकिन यह तेज हो सकता है क्योंकि कोई भी रेग्जाप्स ( sed) या यहां तक ​​कि स्ट्रिंग विभाजन ( awk) का उपयोग नहीं किया जाता है।)
ग्रेविटी

BTW, मैं प्रदर्शन के बारे में उत्सुक था और यहाँ बैश, sed और awk का उपयोग करके मेरे सरल बेंचमार्क के परिणाम हैं। पाठ की लगभग 1000 पंक्तियों (dmesg output) को FIFO फ़ाइल में डालना और फिर उन्हें इस तरह पढ़ना: pastebin.ca/1606844 लुक्स जैसा लगता है कि विजेता है। कोई विचार क्यों?
इल्या ज़करुस्की

1
समय-समय पर चलने वाले परीक्षणों की तरह सावधानी बरतें - सभी 6 अलग-अलग आदेशों में उन्हें चलाने की कोशिश करें और फिर परिणामों का औसत। ब्लॉक कैश इफेक्ट्स को कम करने और बैकग्राउंड रुकावट / शेड्यूलिंग इफेक्ट्स को कम करने के लिए अलग-अलग ऑर्डर।
पीजेड

इस प्रश्न को "शेल" टैग किया गया है, न कि "बैश"।
fiatjaf

1
एक फ़ंक्शन में इसे लपेटने के लिए काफी आसान है:function prepend() { while read line; do echo "${1}${line}"; done; }
tzrlk

46

इसे इस्तेमाल करे:

cmd | awk '{print "[ERROR] " $0}'

चियर्स


1
इसका नुकसान यह है कि "[ERROR]" एक परिवर्तनशील नहीं हो सकता, क्योंकि पूरी अभिव्यक्ति एकल-उद्धरण में होनी चाहिए।
user1071136

4
awk -vT="[ERROR] " '{ print T $0 }'याawk -vT="[ERROR]" '{ print T " " $0 }'
Tino

2
T="[ERROR] " awk '{ print ENVIRON["T"] $0 }'याT="[ERROR]" awk '{ print ENVIRON["T"] " " $0 }'
टीनो

आप केवल चर को रोकने के लिए उद्धरणों के दायरे से बाहर निकल सकते हैं: cmd | awk '{print "['$V]' " $0}'- इसका मूल्यांकन एक बार शुरू होने के बाद किया जाना चाहिए, इसलिए कोई प्रदर्शन ओवरहेड नहीं होता है।
रोबर्ट

13

@Grawity के सभी श्रेय के साथ, मैं उनकी टिप्पणी को एक उत्तर के रूप में प्रस्तुत कर रहा हूं, क्योंकि यह मेरे लिए यहां सबसे अच्छा जवाब है।

sed 's/^/[ERROR] /' cmd

यह बैश समाधान के लिए बेहतर क्यों है?
user14645

1
मुझे लगता है कि यह आपके उद्देश्य पर निर्भर करता है। यदि आपका लक्ष्य बस किसी फ़ाइल में प्रत्येक पंक्ति के लिए प्रस्तुत करना है, तो यह एक बहुत ही परिचित उपकरण का उपयोग करके बहुत कम पात्रों के साथ उस लक्ष्य को पूरा करता है। मैं अब तक 10 लाइन बैश स्क्रिप्ट पसंद करता हूं। awkएक लाइनर अच्छा पर्याप्त है, लेकिन मुझे लगता है कि और अधिक लोगों के साथ परिचित हैं sedकी तुलना में awk। बैश स्क्रिप्ट जो करती है उसके लिए अच्छा है, लेकिन ऐसा लगता है कि यह एक सवाल का जवाब दे रहा है जो नहीं पूछा गया था।
एरिक विल्सन

Pjz ने जो जवाब दिया वह भी एक अच्छा एक-लाइनर है। यह अतिरिक्त कार्यक्रम, प्रक्रिया नहीं करता है और थोड़ा तेज चला सकता है
user14645

3
sed X cmdपढ़ता है cmdऔर इसे निष्पादित नहीं करता है। या तो cmd | sed 's/^/[ERROR] /'या sed 's/^/[ERROR] /' <(cmd)या cmd > >(sed 's/^/[ERROR] /')। लेकिन बाद वाले सावधान रहें। यह आप में से वापसी मान का उपयोग करने की अनुमति देता है यहां तक कि , पृष्ठभूमि में चलाता है, तो यह संभावना है कि आप उत्पादन को देखने के बाद समाप्त हो गया cmd। एक फ़ाइल में प्रवेश करने के लिए अच्छा है, यद्यपि। और ध्यान दें कि शायद इससे तेज है । cmdsedawksed
तिनो

अच्छा लगा। यह कमांड आसानी से अलियास है। alias lpad="sed 's/^/ /'"। ERROR के बजाय मैं 4 प्रमुख स्थान सम्मिलित करता हूं। अब, जादू चाल के लिए: ls | lpad | pbcopy4 स्थानों जो यह निशान के रूप में साथ ls उत्पादन पहले जोड़ें जाएगा Markdown के लिए कोड , जिसका अर्थ है कि आप क्लिपबोर्ड (पेस्ट pbcopy यह पकड़ लेता है, Macs पर) सीधे StackOverflow या किसी अन्य markdown संदर्भ में। नहीं किया जा सका awk जवाब (1 कोशिश में) तो यह एक जीत। जबकि पढ़ने समाधान भी उर्फ करने योग्य है, लेकिन मैं यह पाते हैं sed अधिक अर्थपूर्ण। alias
JL Peyret

8

मैंने कुछ स्पीड टेस्ट करने के लिए GitHub रिपॉजिटरी बनाई ।

परिणाम है:

  • सामान्य मामले में, awkसबसे तेज है। sedथोड़ा धीमा है और perlज्यादा धीमा नहीं है sed। जाहिरा तौर पर, वे सभी टेक्स्ट प्रोसेसिंग के लिए अत्यधिक अनुकूलित भाषा हैं।
  • बहुत विशेष स्थितियों में, जहां कांटे हावी होते हैं, अपनी स्क्रिप्ट को संकलित kshस्क्रिप्ट ( shcomp) के रूप में चलाना और भी अधिक प्रसंस्करण समय बचा सकता है। इसके विपरीत, bashसंकलित kshलिपियों की तुलना में मृत धीमी है ।
  • हरा करने के लिए एक सांख्यिकीय रूप से जुड़ा हुआ द्विआधारी बनाना awkलगता है कि यह प्रयास के लायक नहीं है।

इसके विपरीत python, मृत धीमी गति से है, लेकिन मैंने एक संकलित मामले का परीक्षण नहीं किया है, क्योंकि यह आमतौर पर ऐसे स्क्रिप्टिंग मामले में आप क्या करेंगे।

निम्नलिखित प्रकारों का परीक्षण किया जाता है:

while read line; do echo "[TEST] $line"; done
while read -r line; do echo "[TEST] $line"; done
while read -r line; do echo "[TEST]" $line; done
while read -r line; do echo "[TEST]" "$line"; done
sed 's/^/[TEST] /'
awk '{ print "[TEST] " $0 }'
awk -vT="[TEST] " '{ print T $0 }'
awk -vT="[TEST]" '{ print T " " $0 }'
awk -vT="[TEST]" 'BEGIN { T=T " "; } { print T $0 }'
T="[TEST] " awk '{ print ENVIRON["T"] $0 }'
T="[TEST]" awk '{ print ENVIRON["T"] " " $0 }'
T="[TEST]" awk 'BEGIN { T=ENVIRON["T"] " " } { print T $0 }'
perl -ne 'print "[TEST] $_"'

मेरे एक टूल के दो बाइनरी वेरिएंट (यह गति के लिए अनुकूलित नहीं है, हालांकि):

./unbuffered.dynamic -cp'[TEST] ' -q ''
./unbuffered.static -cp'[TEST] ' -q ''

अजगर बफर्ड:

python -uSc 'import sys
for line in sys.stdin: print "[TEST]",line,'

और अजगर अप्रभावित:

python -uSc 'import sys
while 1:
 line = sys.stdin.readline()
 if not line: break
 print "[TEST]",line,'

awk -v T="[TEST %Y%m%d-%H%M%S] " '{ print strftime(T) $0 }'एक टाइमस्टैम्प उत्पादन करने के लिए
Tino


3

मैं एक ऐसा उपाय चाहता था, जो stdout और stderr को संभाले, इसलिए मैंने prepend.shइसे लिखा और अपने रास्ते में रखा:

#!/bin/bash

prepend_lines(){
  local prepended=$1
  while read line; do
    echo "$prepended" "$line"
  done
}

tag=$1

shift

"$@" > >(prepend_lines "$tag") 2> >(prepend_lines "$tag" 1>&2)

अब मैं सिर्फ prepend.sh "[ERROR]" cmd ..."[ERROR]" को cmdप्री- ऑफ कर सकता हूं , जिसके आउटपुट में , और अभी भी स्टडर और स्टाउट अलग है।


मैंने इस दृष्टिकोण की कोशिश की, लेकिन उन >(उप-भागों के साथ कुछ चल रहा था जो मैं काफी हल नहीं कर सकता था। ऐसा लग रहा था कि स्क्रिप्ट पूरी हो रही है, और प्रॉम्प्ट टर्मिनल पर पहुंचने के बाद प्रॉम्प्ट वापस आ गया जो थोड़ा गड़बड़ था। मैं आखिरकार यहां जवाब के साथ आया हूं stackoverflow.com/a/25948606/409638
robert
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.