lcomma() { sed '
$x;$G;/\(.*\),/!H;//!{$!d
}; $!x;$s//\1/;s/^\n//'
}
कि ,किसी भी इनपुट फ़ाइल में केवल एक अंतिम घटना को हटा दिया जाना चाहिए - और यह अभी भी उन लोगों को प्रिंट करेगा जिसमें ,ऐसा नहीं होता है। मूल रूप से, यह उन लाइनों के दृश्यों को बफ़र करता है जिनमें कॉमा नहीं होता है।
जब यह एक अल्पविराम का सामना करता है तो यह वर्तमान लाइन बफर को होल्ड बफर के साथ स्वैप करता है और इस तरह से एक साथ सभी लाइनों को प्रिंट करता है जो पिछले अल्पविराम के बाद हुई थी और इसके होल्ड बफर को मुक्त करती है।
मैं सिर्फ अपनी इतिहास फ़ाइल के माध्यम से खुदाई कर रहा था और यह पाया:
lmatch(){ set "USAGE:\
lmatch /BRE [-(((s|-sub) BRE)|(r|-ref)) REPL [-(f|-flag) FLAG]*]*
" "${1%"${1#?}"}" "$@"
eval "${ZSH_VERSION:+emulate sh}"; eval '
sed " 1x; \\$3$2!{1!H;\$!d
}; \\$3$2{x;1!p;\$!d;x
}; \\$3$2!x;\\$3$2!b'"
$( unset h;i=3 p=:-:shfr e='\033[' m=$(($#+1)) f=OPTERR
[ -t 2 ] && f=$e\2K$e'1;41;17m}\r${h-'$f$e\0m
f='\${$m?"\"${h-'$f':\t\${$i$e\n}\$1\""}\\c' e=} _o=
o(){ IFS=\ ;getopts $p a "$1" &&
[ -n "${a#[?:]}" ] &&
o=${a#-}${OPTARG-${1#-?}} ||
! eval "o=$f;o=\${o%%*\{$m\}*}"
}; a(){ case ${a#[!-]}$o in (?|-*) a=;;esac; o=
set $* "${3-$2$}{$((i+=!${#a}))${a:+#-?}}"\
${3+$2 "{$((i+=1))$e"} $2
IFS=$; _o=${_o%"${3+$_o} "*}$*\
}; while eval "o \"\${$((i+=(OPTIND=1)))}\""
do case ${o#[!$a]} in
(s*|ub) a s 2 '' ;;
(r*|ef) a s 2 ;;
(f*|lag) a ;;
(h*|elp) h= o; break ;;
esac; done; set -f; printf "\t%b\n\t" $o $_o
)\"";}
यह वास्तव में बहुत अच्छा है। हां, यह उपयोग करता है eval, लेकिन यह अपने तर्कों के संख्यात्मक संदर्भ से परे कभी भी इसे पारित नहीं करता है। यह sedएक आखिरी मैच को संभालने के लिए मनमाना स्क्रिप्ट बनाता है । मैं तुम्हें दिखाता हूँ:
printf "%d\" %d' %d\" %d'\n" $(seq 5 5 200) |
tee /dev/fd/2 |
lmatch d^.0 \ #all re's delimit w/ d now
-r '&&&&' \ #-r or --ref like: '...s//$ref/...'
--sub \' sq \ #-s or --sub like: '...s/$arg1/$arg2/...'
--flag 4 \ #-f or --flag appended to last -r or -s
-s\" \\dq \ #short opts can be '-s $arg1 $arg2' or '-r$arg1'
-fg #tacked on so: '...s/"/dq/g...'
यह निम्नलिखित को stderr पर प्रिंट करता है। यह एक lmatchइनपुट है:
5" 10' 15" 20'
25" 30' 35" 40'
45" 50' 55" 60'
65" 70' 75" 80'
85" 90' 95" 100'
105" 110' 115" 120'
125" 130' 135" 140'
145" 150' 155" 160'
165" 170' 175" 180'
185" 190' 195" 200'
इस फंक्शन का evalसंस्करण एक बार अपने सभी तर्कों के माध्यम से पुन: प्रसारित हो जाता है। जैसा कि यह उन पर चलता है यह प्रत्येक स्विच के संदर्भ के आधार पर एक काउंटर को उचित रूप से पुनरावृत्त करता है और अगले पुनरावृत्ति के लिए कई तर्कों को छोड़ देता है। तब से यह प्रति तर्क कुछ चीजों में से एक करता है:
- प्रत्येक विकल्प के लिए विकल्प पार्सर जोड़ता
$aहै $o। संसाधित किए गए प्रत्येक arg के लिए arg count के द्वारा बढ़ाए गए $aमूल्य के आधार पर असाइन किया गया $iहै। $aनिम्नलिखित दो में से एक मान दिया गया है:
a=$((i+=1)) - यह निर्धारित किया जाता है यदि या तो एक लघु-विकल्प के पास इसके तर्क को जोड़ा नहीं जाता है या यदि विकल्प एक लंबा था।
a=$i#-?- इस विकल्प अगर एक छोटी से एक है और असाइन किया गया है है इसके आर्ग इसके परिशिष्ट में होगा।
a=\${$a}${1:+$d\${$(($1))\}}- प्रारंभिक असाइनमेंट के बावजूद, $a'' का मान हमेशा ब्रेसिज़ में लिपटा होता है और - एक -sमामले में - कभी-कभी $iएक और बढ़ जाता है और इसके अतिरिक्त सीमांकित क्षेत्र को जोड़ दिया जाता है।
नतीजा यह है कि evalकिसी भी अज्ञात से युक्त स्ट्रिंग को कभी पास नहीं किया जाता है। कमांड-लाइन तर्कों में से प्रत्येक को उनके संख्यात्मक तर्क संख्या द्वारा संदर्भित किया जाता है - यहां तक कि सीमांकक जो पहले तर्क के पहले चरित्र से निकाला जाता है और केवल समय है जो आपको किसी भी वर्ण का उपयोग करना चाहिए जो कि अपठित है। मूल रूप से, समारोह एक मैक्रो जनरेटर है - यह किसी भी विशेष तरीके से बहस 'मूल्यों की व्याख्या कभी नहीं क्योंकि sedकर सकते हैं (और, ज़ाहिर है जाएगा) आसानी से जब यह स्क्रिप्ट को पार्स करता है कि संभाल। इसके बजाय, यह समझदारी से अपने आर्गन्स को एक काम करने योग्य स्क्रिप्ट में व्यवस्थित करता है।
यहाँ काम पर समारोह के कुछ डिबग उत्पादन है:
... sed " 1x;\\$2$1!{1!H;\$!d
}; \\$2$1{x;1!p;\$!d;x
}; \\$2$1!x;\\$2$1!b
s$1$1${4}$1
s$1${6}$1${7}$1${9}
s$1${10#-?}$1${11}$1${12#-?}
"
++ sed ' 1x;\d^.0d!{1!H;$!d
}; \d^.0d{x;1!p;$!d;x
}; \d^.0d!x;\d^.0d!b
sdd&&&&d
sd'\''dsqd4
sd"d\dqdg
'
और इसलिए lmatchआसानी से फ़ाइल में अंतिम मैच के बाद डेटा को आसानी से लागू करने के लिए इस्तेमाल किया जा सकता है। मेरे द्वारा ऊपर दी गई कमांड का परिणाम है:
5" 10' 15" 20'
25" 30' 35" 40'
45" 50' 55" 60'
65" 70' 75" 80'
85" 90' 95" 100'
101010105dq 110' 115dq 120'
125dq 130' 135dq 140sq
145dq 150' 155dq 160'
165dq 170' 175dq 180'
185dq 190' 195dq 200'
... जो, पिछली बार /^.0/के मिलान के बाद फ़ाइल इनपुट के सबसेट को देखते हुए , निम्नलिखित प्रतिस्थापन को लागू करता है:
sdd&&&&d- $matchखुद के साथ 4 बार बदलता है ।
sd'dsqd4 - पिछले मैच के बाद से लाइन की शुरुआत के बाद चौथा एकल-उद्धरण।
sd"d\dqd2 - डिट्टो, लेकिन विश्व स्तर पर दोहरे उद्धरण चिह्नों के लिए।
और इसलिए, यह प्रदर्शित lmatchकरने के लिए कि कोई फ़ाइल में अंतिम अल्पविराम को हटाने के लिए कैसे उपयोग कर सकता है :
printf "%d, %d %d, %d\n" $(seq 5 5 100) |
lmatch '/\(.*\),' -r\\1
उत्पादन:
5, 10 15, 20
25, 30 35, 40
45, 50 55, 60
65, 70 75, 80
85, 90 95 100