पैटर्न के सामने एक नई लाइन कैसे डालें?


138

एक पंक्ति के भीतर एक पैटर्न से पहले एक नई रेखा कैसे डालें?

उदाहरण के लिए, यह रेगेक्स पैटर्न के पीछे एक नई पंक्ति सम्मिलित करेगा ।

sed 's/regex/&\n/g'

मैं ऐसा कैसे कर सकता हूं, लेकिन पैटर्न के सामने कैसे ?

इस सैंपल इनपुट फ़ाइल को देखते हुए, मैच करने का पैटर्न फोन नंबर है।

some text (012)345-6789

बन जाना चाहिए

some text
(012)345-6789


1
@ निल्सवोनर्थ, एक सीधा सवाल एक बुरा सवाल क्यों है?
जोश

जवाबों:


177

यह लिनक्स और OS X पर परीक्षण bashऔर काम करता है zsh:

sed 's/regexp/\'$'\n/g'

सामान्य तौर पर, $एकल उद्धरणों में एक स्ट्रिंग शाब्दिक के बाद bashसी-स्टाइल बैकलैश प्रतिस्थापन होता है, उदाहरण के $'\t'लिए एक शाब्दिक टैब में अनुवाद किया जाता है। इसके अलावा, sed चाहता है कि आपका न्यूलाइन शाब्दिक बैकस्लैश के साथ बच जाए, इसलिए \पहले $। और अंत में, डॉलर के संकेत को स्वयं उद्धृत नहीं किया जाना चाहिए, ताकि यह शेल द्वारा व्याख्या की जाए, इसलिए हम उद्धरण को पहले बंद कर देते हैं $और फिर इसे फिर से खोलते हैं।

संपादित करें : जैसा कि @ mklement0 द्वारा टिप्पणियों में सुझाया गया है, यह भी काम करता है:

sed $'s/regexp/\\\n/g'

यहां क्या होता है: पूरी सीड कमांड अब एक सी-स्टाइल स्ट्रिंग है, जिसका अर्थ है कि बैकस्लैश कि सीड को नई लाइन शाब्दिक से पहले रखा जाना चाहिए, अब एक और बैकस्लैश के साथ बच जाना चाहिए। हालांकि अधिक पठनीय, इस मामले में आप शेल स्ट्रिंग प्रतिस्थापन (बिना इसे फिर से बदसूरत बनाने) करने में सक्षम नहीं होंगे।


7
यह मुझे OSX पर "बिना बदले नई लाइन के अंदर विकल्प देता है"।
मैट गिब्सन

@Matt गिब्सन बहुत अजीब है क्योंकि "अनसैप्ड न्यूलाइन" केवल तभी दी जाती है जब आपके पास प्रतिस्थापन पैटर्न के भीतर बैकस्लैश के बिना एक वास्तविक न्यूलाइन होती है। उपरोक्त मेरा कोड काम करता है, वास्तव में, कुछ अन्य गोले में भी, जैसे zsh, ksh।
मोजुबा

3
@Matt गिब्सन ... या यदि आप मेरे कोड में '$' \ n से पहले बैकस्लैश भूल जाते हैं।
मोजुबा

7
जैसा कि लिखा गया है, ये अभिव्यक्तियाँ regex को पूरी तरह से एक नई पंक्ति के साथ प्रतिस्थापित करती हैं, बजाय एक मौजूदा पंक्ति के बीच में एक अनुरोध के रूप में एक नई पंक्ति सम्मिलित करने के। यहां बताया गया है कि कैसे मैंने दो मिलान पैटर्न के बीच एक नई पंक्ति सम्मिलित करने के लिए इस उत्तर के संशोधित रूप का उपयोग किया sed '\(first match\)\(second match\)/\1\'$'\n''\2/g':। \ N के बाद दो एकल उद्धरण नोट करें। पहले " $" खंड को बंद कर देता है ताकि शेष रेखा इससे प्रभावित न हो। उन उद्धरणों के बिना, \ 2 को नजरअंदाज कर दिया गया था।
डेविड रवेती

12
एक अन्य विकल्प एक एकल एएनएसआई सी-उद्धृत स्ट्रिंग का उपयोग करना है : sed $'s/regexp/\\\n/g'जो पठनीयता में सुधार करता है - एकमात्र चेतावनी यह है कि आपको तब सभी शाब्दिक वर्णों को दोगुना करने की आवश्यकता है \
3

43

कुछ अन्य उत्तरों ने मेरे सेड के संस्करण के लिए काम नहीं किया। की स्थिति को बदल दिया &और \nकाम किया।

sed 's/regexp/\n&/g' 

संपादित करें: यह OS X पर काम नहीं करता है, जब तक आप इंस्टॉल नहीं करते हैं gnu-sed


9
मुझे यकीन नहीं है कि यह सेड के सभी संस्करणों में काम करता है। मैं अपने मैक पर यह कोशिश की और \ n बस 'एन' के रूप में उत्पादन हो जाता है
टोड गैंबलिन

3
अपना जवाब पढ़ने से पहले, मेरे काम पर मैक पर 15 मिनट बिताए। जाओ Apple!
रिक 77

1
होमब्रे का उपयोग करने वालों के लिए: brew install gnu-sedइसके बादgsed 's/regexp/\n&/g'
आआआआआ

1
... इसके बादecho 'alias sed=gsed' >> ~/.bashrc
Proximo

36

Sed में, आप आउटपुट स्ट्रीम में आसानी से newlines नहीं जोड़ सकते। आपको एक निरंतरता रेखा का उपयोग करने की आवश्यकता है, जो अजीब है, लेकिन यह काम करता है:

$ sed 's/regexp/\
&/'

उदाहरण:

$ echo foo | sed 's/.*/\
&/'

foo

देखें यहाँ जानकारी के लिए। यदि आप कुछ कम अजीब चाहते हैं तो आप perl -pesed के बजाय मैच समूहों के साथ प्रयोग कर सकते हैं :

$ echo foo | perl -pe 's/(.*)/\n$1/'

foo

$1 नियमित अभिव्यक्ति में पहले मिलान वाले समूह को संदर्भित करता है, जहां समूह कोष्ठक में हैं।


आप यह क्यों कहते हैं कि आप नई सूची नहीं जोड़ सकते हैं? आप बस sed / s regexp / & \ n / g 'कर सकते हैं
Andres

2
यह कम से कम हैक करने वाली चीज़ है जिसे आप मैक पर न्यूलाइन डालने के लिए कर सकते हैं (\ n किसी मैक पर काम नहीं करता है)
पाइलिनक्स

पर्ल संस्करण को संपादित करने के लिए संशोधित किया जा सकता हैperl -pi -e 's/(.*)/\n$1/' foo
नामांक

2
@ संकेत: (अधिकतर) POSIX-features-only Sed कार्यान्वयन जैसे BSD संस्करण, जो OS X के साथ भी आता है, sफ़ंक्शन कॉल के प्रतिस्थापन भाग ( GNU Sed कार्यान्वयन, जो करता है) के विपरीत नियंत्रण-वर्ण एस्केप अनुक्रम का समर्थन नहीं करता है । उपरोक्त उत्तर दोनों कार्यान्वयन के साथ काम करता है; सभी अंतरों के अवलोकन के लिए, यहाँ देखें ।
mklement0

29

मेरे मैक पर, निम्नलिखित में नई लाइन के बजाय एक एकल 'एन' सम्मिलित है:

sed 's/regexp/\n&/g'

यह नई पंक्ति के साथ बदलता है:

sed "s/regexp/\\`echo -e '\n\r'`/g"

मैं इनलाइन एडिट कर रहा था sed -i '' -e ...और ^Mफ़ाइल को लिखे जाने पर एक केयरट एम (ctrl + m) की समस्या हो रही थी। मैं उसी params के साथ पर्ल का उपयोग कर समाप्त हो गया।
स्टीव तौबर

2
कृपया इस तथ्य से अवगत रहें कि दूसरा कोड एक विशेष न्यूलाइन कोड LF CR (MS-DOS CR LF का उल्टा) सम्मिलित करता है! यूनिक्स की तरह ओएस और मैक ओएस एक्स दोनों ही एलएफ ( \n) का उपयोग करते हैं ।
पाबौक

मेरी सीड एक्सप्रेशन में कुछ और कारण इतनी नाखुशी पैदा कर रहा था (इसके बावजूद echo...और न्यूलाइन के बिना ठीक काम करना ) कि मैंने अभी-अभी ऐसा किया है।
अहमद फ़सीह

1
या बस: sed "s/regexp/`echo`/g"- यह एलएफ-सीआर के बजाय एक एकल एलएफ का उत्पादन करेगा
मोजुबा

2
@mojuba: नहीं: खाली स्ट्रिंग`echo` में परिणाम होगा , क्योंकि कमांड प्रतिस्थापन हमेशा सभी अनुगामी newlines को ट्रिम करते हैं। एक एकल न्यूलाइन (और डालने - यानी, एक अतिरिक्त सीआर - एक भयानक विचार है) को सीधे सम्मिलित करने के लिए कमांड प्रतिस्थापन का उपयोग करने का कोई तरीका नहीं है । \n\r
mklement0

15
echo one,two,three | sed 's/,/\
/g'

1
+1 ने पूरी तरह से और बहुत
संघर्षपूर्ण

2
यह जवाब वास्तव में एक बैश समाधान के बजाय एक sed समाधान है। कुछ भी जो निर्माण का उपयोग करता है जैसे कि नई लाइन उत्पन्न करने के लिए शेल पर निर्भर है। इस तरह के समाधान पोर्टेबल नहीं हो सकते हैं। यह एक है। निश्चित रूप से, यह 2009 से tgamblin के उत्तर में दूसरे उदाहरण का एक डुप्लिकेट है।$'\n'
ghoti

10

इस मामले में, मैं sed का उपयोग नहीं करता हूं। मैं tr का उपयोग करता हूं।

cat Somefile |tr ',' '\012' 

यह कॉमा लेता है और इसे गाड़ी की वापसी के साथ बदल देता है।


1
मैंने पाया कि यह भी काम करता है: cat Somefile | tr ',' '\n'YMMV
LS

9

आप पर्ल वन-लाइनर्स का बहुत उपयोग कर सकते हैं जैसे कि आप sed के साथ करते हैं, पूर्ण पर्ल रेगुलर एक्सप्रेशन सपोर्ट का लाभ उठाते हैं (जो कि sed के साथ बहुत अधिक शक्तिशाली है)। * निक्स प्लेटफार्मों में भी बहुत कम भिन्नता है - पर्ल आम तौर पर पर्ल है। तो आप इस बारे में चिंता करना बंद कर सकते हैं कि आपके सिस्टम के सीड के संस्करण को कैसे बनाया जाए जो आप चाहते हैं।

इस मामले में, आप कर सकते हैं

perl -pe 's/(regex)/\n$1/'

-pe पर्ल को "निष्पादित और प्रिंट करें" लूप में रखा जाता है, जो कि ऑपरेशन के सामान्य मोड के समान है।

' शेल के हस्तक्षेप नहीं करेगा तो सब कुछ उद्धरण

()regex के आसपास एक समूह संचालक है। $1प्रतिस्थापन के दाईं ओर जो कुछ भी इन पार्न्स के अंदर मिलान किया गया था उसे प्रिंट करता है।

अंत में, \nएक नई पंक्ति है।

भले ही आप एक समूह संचालक के रूप में कोष्ठक का उपयोग कर रहे हों, आपको किसी भी ऐसे कोष्ठक से बचना होगा, जिसे आप मिलान करने का प्रयास कर रहे हैं। तो आपके द्वारा ऊपर दी गई सूची से मेल खाने वाला रेगेक्स कुछ ऐसा होगा

\(\d\d\d\)\d\d\d-\d\d\d\d

\(या \)शाब्दिक शब्द मेल करता है, और \dएक अंक मेल खाता है।

बेहतर:

\(\d{3}\)\d{3}-\d{4}

मुझे लगता है कि आप समझ सकते हैं कि ब्रेसिज़ में नंबर क्या कर रहे हैं।

इसके अतिरिक्त, आप अपने regex के लिए / के अलावा अन्य सीमांकक का उपयोग कर सकते हैं। इसलिए यदि आपको मिलान करने की आवश्यकता है / तो आपको इससे बचने की आवश्यकता नहीं होगी। मेरे जवाब की शुरुआत में या तो नीचे रेगेक्स के बराबर है। सिद्धांत रूप में आप मानक / के लिए किसी भी वर्ण को प्रतिस्थापित कर सकते हैं ।

perl -pe 's#(regex)#\n$1#'
perl -pe 's{(regex)}{\n$1}'

एक अंतिम विचार।

इसी तरह -neके -peकृत्यों के बजाय उपयोग करना , लेकिन अंत में स्वचालित रूप से प्रिंट नहीं होता है। यदि आप स्वयं प्रिंट करना चाहते हैं तो यह आसान हो सकता है। जैसे, यहाँ एक grep-alike है ( m/foobar/एक रेगेक्स मैच है):

perl -ne 'if (m/foobar/) {print}'

यदि आप नए-नए कष्टों से जूझ रहे हैं, और आप चाहते हैं कि यह आपके लिए जादुई रूप से संभाला जाए, तो -l। ओपी के लिए उपयोगी नहीं है, जो नई कहानियों के साथ काम कर रहा था, हालांकि।

बोनस टिप - यदि आपके पास पीसीआर पैकेज स्थापित है, तो यह आता है pcregrep, जिसमें पूर्ण पर्ल-संगत रेगेक्स का उपयोग किया जाता है।


4

हम्म, अभी बची हुई नई सुर्खियों में sed( हाल ही में मेरे पास GNU sed 4.2.1 है) के अधिक संस्करणों में काम करना प्रतीत होता है ,

dev:~/pg/services/places> echo 'foobar' | sed -r 's/(bar)/\n\1/;'
foo
bar

1
जैसा कि उल्लेख किया गया है, यह GNU sed के विभिन्न संस्करणों के साथ काम करता है, लेकिन macOS के साथ शामिल नहीं sed।
एलएस

4
echo pattern | sed -E -e $'s/^(pattern)/\\\n\\1/'

()समर्थन के साथ एल कैप्टन पर ठीक काम किया


इसने बहुत अच्छा काम किया और आप अपने स्वयं के उद्देश्य के लिए विशेषज्ञ को परीक्षण करने और अतिरिक्त रूप से पूरा करने की पूरी आज्ञा देते हैं। अच्छी नौकरी!
jxramos

3

लिनक्स पर आउटपुट स्ट्रीम में एक नई लाइन डालने के लिए, मैंने उपयोग किया:

sed -i "s/def/abc\\\ndef/" file1

कहाँ file1था:

def

इन-प्लेस प्रतिस्थापन से पहले, और:

abc
def

इन-प्लेस रिप्लेसमेंट के बाद। कृपया के उपयोग पर ध्यान दें \\\n। यदि पैटर्न के "अंदर है, तो उपयोग से बचो \"


मेरे लिए उपरोक्त कोड काम नहीं करता है। एलएफ के बजाय sedआवेषण \nक्योंकि यह \\nशेल से पैरामीटर में मिलता है। --- यह कोड काम करता है sed -i "s/def/abc\ndef/" file1:। --- GNU sed version 4.2.1, GNU bash, version 4.1.2(1) / 4.2.25(1)(CentOS रिलीज 6.4 / Ubuntu 12.04.3)।
पाबूक

2

sed में आप अपने पैटर्न में "\ 1", "\ 2" के साथ समूहों को संदर्भित कर सकते हैं, .... इसलिए यदि आप जिस पैटर्न की तलाश कर रहे हैं वह "PATTERN" है, और आप इसके सामने "BEFORE" डालना चाहते हैं , आप का उपयोग कर सकते हैं, बच भागने

sed 's/(PATTERN)/BEFORE\1/g'

अर्थात

  sed 's/\(PATTERN\)/BEFORE\1/g'

बस किया: परीक्षण सामग्री = "एबीसी एबीसी एबीसी"। Ran "sed 's / \ (ABC \) / \ n \ / 1 / g' परीक्षण में, नई भावनाएँ मिलीं। पलायन के साथ प्रयोग करें, अपने पैटर्न में एक समय में 1 चीज़ जोड़ने की कोशिश करें, उदाहरण के लिए सुनिश्चित करें कि आप मिलान कर रहे हैं। पैटर्न, फिर समूह मिलान की जाँच करें, फिर न्यूलाइन चेकिंग जोड़ें।
स्टीव बी।

मैंने अभी ठीक वैसा ही प्रयास किया है और "nABC nABC nABC 'प्राप्त किया है। क्या आप सिंक के कुछ अन्य संस्करण का उपयोग कर रहे हैं?
Todd Gamblin

शेल बचना संभवतया tgamblin के प्रयासों के रास्ते में हो रहा है। स्टीव बी जैसे एकल उद्धरणों में पूर्ण sed तर्क डालकर इसे ठीक करना चाहिए। हालांकि संभव है कि सेड के अलग-अलग संस्करण न्यूलाइन के लिए \ n न समझें।
डैन प्रिट्स

2

आप -vपैटर्न प्रदान करने के लिए , awk के साथ भी ऐसा कर सकते हैं :

awk -v patt="pattern" '$0 ~ patt {gsub(patt, "\n"patt)}1' file

यह जाँचता है कि क्या किसी पंक्ति में एक दिया हुआ पैटर्न है। यदि हां, तो यह इसकी शुरुआत के लिए एक नई लाइन जोड़ता है।

एक मूल उदाहरण देखें:

$ cat file
hello
this is some pattern and we are going ahead
bye!
$ awk -v patt="pattern" '$0 ~ patt {gsub(patt, "\n"patt)}1' file
hello
this is some 
pattern and we are going ahead
bye!

ध्यान दें कि यह एक पंक्ति में सभी पैटर्न को प्रभावित करेगा:

$ cat file
this pattern is some pattern and we are going ahead
$ awk -v patt="pattern" '$0 ~ patt {gsub(patt, "\n"patt)}1' d
this 
pattern is some 
pattern and we are going ahead

1
इसमें 1 क्या करता है?
whatahitson

1
@whatahitson 1को एक शॉर्टहैंड के रूप में अवाक में प्रयोग किया जाता है {print $0}। कारण यह है कि कोई भी शर्त जो ट्रू के डिफ़ॉल्ट एक्शन को ट्रिगर करती है, का मूल्यांकन करती है, जिसमें वर्तमान रिकॉर्ड को प्रिंट करना शामिल है।
फेडोरक्वी 'एसओ

1

यह मेरे लिए मैक में काम करता है

sed -i.bak -e 's/regex/xregex/g' input.txt sed -i.bak -e 's/qregex/\'$'\nregex/g' input.txt

डोनो क्या इसकी सही एक ...


1

इस प्रश्न के सभी उत्तरों को पढ़ने के बाद, मुझे अभी भी निम्न उदाहरण स्क्रिप्ट के लिए सही सिंटैक्स प्राप्त करने के लिए कई प्रयास करने पड़े:

#!/bin/bash
# script: add_domain
# using fixed values instead of command line parameters $1, $2
# to show typical variable values in this example
ipaddr="127.0.0.1"
domain="example.com"
# no need to escape $ipaddr and $domain values if we use separate quotes.
sudo sed -i '$a \\n'"$ipaddr www.$domain $domain" /etc/hosts

स्क्रिप्ट \nएकल sedकमांड का उपयोग करके एक फ़ाइल के अंत में पाठ की एक और पंक्ति के बाद एक नई पंक्ति को जोड़ता है ।


1
sed -e 's/regexp/\0\n/g'

\ 0 शून्य है, इसलिए आपकी अभिव्यक्ति को शून्य (कुछ नहीं) से बदल दिया गया है और फिर ...
\ n नई लाइन है

यूनिक्स के कुछ स्वादों पर काम नहीं करता है, लेकिन मुझे लगता है कि यह आपकी समस्या का समाधान है।

echo "Hello" | sed -e 's/Hello/\0\ntmow/g'
Hello
tmow

0

Vi पर Red Hat में, मैं सिर्फ \ r वर्ण का उपयोग करके कैरिज रिटर्न सम्मिलित करने में सक्षम था। मेरा मानना ​​है कि यह आंतरिक रूप से 'सेड' के बजाय 'पूर्व' को निष्पादित करता है, लेकिन यह समान है, और vi कोड पैच जैसे बल्क एडिट करने का एक और तरीका हो सकता है। उदाहरण के लिए। मैं एक खोज शब्द के साथ आसपास हूं यदि एक कथन है कि ब्रेसिज़ के बाद गाड़ी वापसी पर जोर देता है:

:.,$s/\(my_function(.*)\)/if(!skip_option){\r\t\1\r\t}/

ध्यान दें कि मैंने भी चीजों को बेहतर संरेखित करने के लिए कुछ टैब डाले थे।

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