मैं एक awk स्क्रिप्ट में शेल चर का उपयोग कैसे करूं?


290

मैं एक के लिए बाहरी खोल चर पारित करने के लिए कुछ तरीके पाया awkस्क्रिप्ट है, लेकिन मैं के बारे में उलझन में हूँ 'और "

सबसे पहले, मैंने एक शेल स्क्रिप्ट के साथ कोशिश की:

$ v=123test
$ echo $v
123test
$ echo "$v"
123test

फिर जागने की कोशिश की:

$ awk 'BEGIN{print "'$v'"}'
$ 123test
$ awk 'BEGIN{print '"$v"'}'
$ 123

अंतर क्यों है?

अंत में मैंने यह कोशिश की:

$ awk 'BEGIN{print " '$v' "}'
$  123test
$ awk 'BEGIN{print ' "$v" '}'
awk: cmd. line:1: BEGIN{print
awk: cmd. line:1:             ^ unexpected newline or end of string 

मैं इस बारे में उलझन में हूँ।


2
मुझे -v जैसा कि नीचे दिखाया गया है, लेकिन यह वास्तव में यह सोचने के लिए एक महान अभ्यास है कि चीजों को शेल से कैसे बचाया जाए। इसके माध्यम से काम करते हुए, मेरा पहला कट स्पेस और डॉलर संकेतों पर बैकस्लैश का उपयोग करता है। कहने की जरूरत नहीं है कि यहां के उदाहरण मेरे समय के लायक थे।
क्रिस


यदि आपकी अजीब खोज को नियमित अभिव्यक्ति की आवश्यकता है , तो आप नहीं डाल सकते /var/। इसके बजाय, टिल्ड का उपयोग करें:awk -v var="$var" '$0 ~ var'
नोम मानोस

जवाबों:


496

में शेल चर प्राप्त करना awk

कई तरीकों से किया जा सकता है। दूसरों की तुलना में कुछ बेहतर हैं। यह उनमें से ज्यादातर को कवर करना चाहिए। यदि आपके पास कोई टिप्पणी है, तो कृपया नीचे दें। v1.5


का उपयोग कर -v (सबसे अच्छा तरीका है, सबसे पोर्टेबल)

-vविकल्प का उपयोग करें : (PS एक जगह का उपयोग करें -vया उसके बाद कम पोर्टेबल होगा। जैसे, awk -v var=नहीं awk -vvar=)

variable="line one\nline two"
awk -v var="$variable" 'BEGIN {print var}'
line one
line two

यह अधिकांश के साथ संगत होना चाहिए awk, और चर BEGINब्लॉक में भी उपलब्ध है:

यदि आपके पास कई चर हैं:

awk -v a="$var1" -v b="$var2" 'BEGIN {print a,b}'

चेतावनी दी । जैसा कि एड मॉर्टन लिखते हैं, एस्केप सीक्वेंस की व्याख्या की जाएगी तो \tयह एक वास्तविक बन जाता है tabऔर ऐसा नहीं \tहै कि आप क्या खोज रहे हैं। के ENVIRON[]माध्यम से इसका उपयोग या उपयोग करके हल किया जा सकता हैARGV[]

पुनश्च यदि आप विभाजक के रूप में तीन ऊर्ध्वाधर बार पसंद करते हैं |||, तो यह बच नहीं सकता है, इसलिए उपयोग करें-F"[|][|][|]"

किसी कार्यक्रम / फ़ंक्शन से डेटा प्राप्त करने पर उदाहरण awk(यहाँ दिनांक का उपयोग किया जाता है)

awk -v time="$(date +"%F %H:%M" -d '-1 minute')" 'BEGIN {print time}'

कोड ब्लॉक के बाद चर

यहां हमें awkकोड के बाद वेरिएबल मिलता है । यह तब तक ठीक काम करेगा जब तक आपको BEGINब्लॉक में वैरिएबल की आवश्यकता न हो :

variable="line one\nline two"
echo "input data" | awk '{print var}' var="${variable}"
or
awk '{print var}' var="${variable}" file
  • कई चर जोड़ना:

awk '{print a,b,$0}' a="$var1" b="$var2" file

  • इस तरह हम FSप्रत्येक फाइल के लिए अलग फील्ड सेपरेटर भी सेट कर सकते हैं ।

awk 'some code' FS=',' file1.txt FS=';' file2.ext

  • कोड ब्लॉक के बाद वेरिएबल ब्लॉक के लिए काम नहीं करेगा BEGIN:

echo "input data" | awk 'BEGIN {print var}' var="${variable}"


यहाँ-स्ट्रिंग

परिवर्तनीय को यहां गोले से स्ट्रिंगawk का उपयोग करके भी जोड़ा जा सकता है जो उन्हें समर्थन करते हैं (बैश सहित):

awk '{print $0}' <<< "$variable"
test

यह समान है:

printf '%s' "$variable" | awk '{print $0}'

PS इस चर को फ़ाइल इनपुट के रूप में मानता है।


ENVIRON इनपुट

जैसा कि TrueY लिखता है, आप पर्यावरण चरENVIRON प्रिंट करने के लिए उपयोग कर सकते हैं । AWK चलाने से पहले एक चर सेट करना, आप इसे इस तरह प्रिंट कर सकते हैं:

X=MyVar
awk 'BEGIN{print ENVIRON["X"],ENVIRON["SHELL"]}'
MyVar /bin/bash

ARGV इनपुट

जैसा कि स्टीवन पेनी लिखते हैं, आप ARGVडेटा को जागृत करने के लिए उपयोग कर सकते हैं :

v="my data"
awk 'BEGIN {print ARGV[1]}' "$v"
my data

कोड में डेटा प्राप्त करने के लिए, केवल BEGIN नहीं:

v="my data"
echo "test" | awk 'BEGIN{var=ARGV[1];ARGV[1]=""} {print var, $0}' "$v"
my data test

कोड के भीतर परिवर्तनशील: उपयोग के साथ उपयोग

आप awkकोड के भीतर एक चर का उपयोग कर सकते हैं , लेकिन यह गड़बड़ है और पढ़ने में कठिन है, और जैसा कि Charles Duffyबताते हैं, यह संस्करण भी कोड इंजेक्शन का शिकार हो सकता है। यदि कोई वैरिएबल में खराब सामान जोड़ता है, तो इसे awkकोड के हिस्से के रूप में निष्पादित किया जाएगा ।

यह कोड के भीतर चर को निकालकर काम करता है, इसलिए यह इसका एक हिस्सा बन जाता है।

यदि आप awkवैरिएबल के उपयोग से गतिशील रूप से परिवर्तन करना चाहते हैं , तो आप इसे इस प्रकार कर सकते हैं, लेकिन सामान्य चर के लिए इसका उपयोग न करें।

variable="line one\nline two"
awk 'BEGIN {print "'"$variable"'"}'
line one
line two

यहाँ कोड इंजेक्शन का एक उदाहरण दिया गया है:

variable='line one\nline two" ; for (i=1;i<=1000;++i) print i"'
awk 'BEGIN {print "'"$variable"'"}'
line one
line two
1
2
3
.
.
1000

आप awkइस तरह से बहुत सारी कमांड जोड़ सकते हैं । यहां तक ​​कि इसे गैर-मान्य आदेशों के साथ क्रैश करें।


अधिक जानकारी:

दोहरे भाव का उपयोग

यह हमेशा दोहरे चर चर के लिए अच्छा है "$variable"
यदि नहीं, तो एक लंबी एकल रेखा के रूप में कई लाइनें जोड़ी जाएंगी।

उदाहरण:

var="Line one
This is line two"

echo $var
Line one This is line two

echo "$var"
Line one
This is line two

अन्य त्रुटियाँ जिन्हें आप बिना दोहरे उद्धरण के प्राप्त कर सकते हैं:

variable="line one\nline two"
awk -v var=$variable 'BEGIN {print var}'
awk: cmd. line:1: one\nline
awk: cmd. line:1:    ^ backslash not last character on line
awk: cmd. line:1: one\nline
awk: cmd. line:1:    ^ syntax error

और एकल उद्धरण के साथ, यह चर के मूल्य का विस्तार नहीं करता है:

awk -v var='$variable' 'BEGIN {print var}'
$variable

AWK और चर के बारे में अधिक जानकारी

इस FAQ पढ़ें


2
"गड़बड़ और पढ़ने में कठिन" कोड इंजेक्शन के अधिक महत्वपूर्ण सुरक्षा चिंता को अनदेखा करता है जब सीधे awk कोड में तारों को प्रतिस्थापित करता है।
चार्ल्स डफी

ऊपर दिए गए उत्तर को पढ़कर मैं अपनी स्क्रिप्ट को त्रुटियों के बिना चला सकता हूं, लेकिन यह काम नहीं करता है: awk -v repo = "$ 1" -v टैग = "$ 2" '{उप (/ छवि: रजिस्ट्रीबक्स .azurecr.io \ / { प्रिंट रेपो}:: ([a-z0-9] +) $ /, "छवि: रजिस्ट्रीबजाजुरेक्र्र। io / {प्रिंट रेपो}: {प्रिंट टैग}");} १ ’./services/appy.gov.in newcompose.yaml। नेस्टेड कोष्ठक {के कारण है?
दारियन बैडलडोन

@DarionBadlydone यह कोशिश करो awk -v repo="$1" -v tag="$2" 'BEGIN {print "repo="repo,"tag="tag}'। यह देखेगा कि यह चर को प्रिंट करता है या नहीं। यदि आप यह पता नहीं लगा सकते हैं तो अपना स्वयं का प्रश्न पोस्ट करें।
जोतेन

@ जो हां यह मानों को प्रिंट करता है, इसलिए मैंने इस तरह से कोशिश की: awk -v repo = "$ 1" -v टैग = "$ 2" '{प्रिंट "{उप (/ छवि: रजिस्ट्रीबाउजरैक्रियो.आईओ / मैप्सपो] :( [a-z0-9] +) $ /, \ "छवि: रजिस्ट्रीकरण इत्यादिcr.io/"repo":"tag"\"); Ideal1"} './services/appscompose.yaml/ newcompose.yaml लेकिन आकांक्षी के रूप में काम नहीं कर रहा है। यह स्रोत फ़ाइल की प्रत्येक पंक्ति को मुद्रित कमांड
डारियन बैडलडोन

@ जोतने मैंने इसे सेड के साथ किया, वैसे भी शुक्रिया
दारियन बैडलडोन

28

ऐसा लगता है कि अच्छा-पुराना ENVIRON बिल्ट-इन हैश का उल्लेख बिल्कुल नहीं है। इसके उपयोग का एक उदाहरण:

$ X=Solaris awk 'BEGIN{print ENVIRON["X"], ENVIRON["TERM"]}'
Solaris rxvt

4
यह एक अच्छा सुझाव है क्योंकि यह डेटा शब्दशः गुजरता है। -vजब मान में बैकस्लैश होता है तो काम नहीं करता है।
कि अन्य लड़के

2
@thatotherguy मुझे नहीं पता था कि! मैंने सोचा कि अगर मैं इस्तेमाल करता हूं awk -v x='\c\d' ...तो इसका सही इस्तेमाल किया जाएगा। लेकिन जब awkx छपा होता है तो वह प्रसिद्ध हो जाता है: त्रुटि संदेश ... धन्यवाद! awk: warning: escape sequence '\c' treated as plain 'c'
TrueY

यह ठीक से काम करता है - इस संदर्भ में ठीक से मतलब है कि एस्केप सीक्वेंस का विस्तार करें क्योंकि यह -vकाम करने के लिए डिज़ाइन किया गया था ताकि आप \tचर में उपयोग कर सकें और उदाहरण के लिए, यह डेटा में शाब्दिक टैब से मेल खाता हो। यदि वह व्यवहार नहीं है जो आप चाहते हैं तो आप उपयोग नहीं करते -vहैं ARGV[]या ENVIRON[]
एड मॉर्टन

9

इनमें से किसी एक का उपयोग करें कि आप शेल वेरिएबल्स में बैकस्लैश कैसे चाहते हैं ( avarयह एक अजीब वैरिएबल है, svarशेल वेरिएबल है):

awk -v avar="$svar" '... avar ...' file
awk 'BEGIN{avar=ARGV[1];ARGV[1]=""}... avar ...' "$svar" file

विवरण और अन्य विकल्पों के लिए http://cfajohnson.com/shell/cus-faq-2.html#Q24 देखें । उपरोक्त पहली विधि लगभग हमेशा आपका सबसे अच्छा विकल्प है और इसमें सबसे स्पष्ट शब्दार्थ है।


6

आप चर नाम ( ) और पर्यावरण चर के मान ( ) के साथ कमांड लाइन विकल्प में पास कर सकते हैं :-vv="${v}"

% awk -vv="${v}" 'BEGIN { print v }'
123test

या इसे स्पष्ट करने के लिए (बहुत कम vएस के साथ):

% environment_variable=123test
% awk -vawk_variable="${environment_variable}" 'BEGIN { print awk_variable }'
123test

3

आप ARGV का उपयोग कर सकते हैं:

v=123test
awk 'BEGIN {print ARGV[1]}' "$v"

ध्यान दें कि यदि आप शरीर में जारी रखने जा रहे हैं, तो आपको ARGC को समायोजित करने की आवश्यकता होगी:

awk 'BEGIN {ARGC--} {print ARGV[2], $0}' file "$v"

1

मैंने सिर्फ "लूप के लिए" जोत्ने का उत्तर बदल दिया।

for i in `seq 11 20`; do host myserver-$i | awk -v i="$i" '{print "myserver-"i" " $4}'; done

1
यह केवल अक्क के -vविकल्प का उपयोग करने का एक और उदाहरण प्रतीत होता है, जो पहले से मौजूद कई उत्तरों में उल्लिखित था। यदि आप यह दिखाना चाहते हैं कि एक लूप में अवाक को कैसे चलाना है, तो यह वास्तव में एक अलग सवाल है।
ट्रिपल जूल

0

मुझे लॉग फाइल की तर्ज पर शुरुआत में तारीख डालनी थी और यह नीचे की तरह किया गया:

DATE=$(date +"%Y-%m-%d")
awk '{ print "'"$DATE"'", $0; }' /path_to_log_file/log_file.log

इसे सहेजने के लिए किसी अन्य फ़ाइल पर रीडायरेक्ट किया जा सकता है


डबल उद्धरण - एकल उद्धरण - डबल उद्धरण बिल्कुल वही था जो मुझे अपना काम बनाने के लिए आवश्यक था।
user53029

2
यह पहले से ही स्वीकृत जवाब में एक विधि के रूप में उल्लेख किया गया था जिसे आपको कोड इंजेक्शन कमजोरियों के कारण उपयोग नहीं करना चाहिए। तो यहां जानकारी बेमानी है (पहले से ही स्वीकृत उत्तर में वर्णित है), और अपूर्ण (इस पद्धति के साथ समस्याओं का उल्लेख नहीं करता है)।
जेसन एस
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.