मैं / * ... * / सहित / / / और * / के अंतर्गत आने वाले सभी वर्णों को कैसे हटा सकता हूं?


12

मैंने sed और awk की कोशिश की, लेकिन इसके चरित्र के रूप में काम नहीं करने में "/" शामिल है जो पहले से ही सीमांकक के रूप में कमांड में है।

कृपया मुझे बताएं कि मैं इसे कैसे प्राप्त कर सकता हूं।

नीचे एक नमूना उदाहरण दिया गया है। हम टिप्पणी किए गए अनुभागों को हटाना चाहते हैं /*.....*/

/*This is to print the output
data*/
proc print data=sashelp.cars;
run;
/*Creating dataset*/
data abc;
set xyz;
run;

-बश-4.1 $ सेड की, / *। ** /, जी 'की परीक्षा। एसस नीचे ouput मैं मिलता है, पहली टिप्पणी अभी भी वहाँ है। / * यह आउटपुट डेटा प्रिंट करने के लिए है * / प्रिंट डेटा खरीदे = sashelp.cars; Daud; डेटा एबीसी; xyz सेट करें; Daud;
शरीक आलम

1
संपादन के लिए धन्यवाद। यह बेहतर होगा यदि आप अपने वांछित आउटपुट को भी शामिल करते हैं। इसमें यह भी शामिल करें कि आपने क्या प्रयास किया और यह कैसे टिप्पणी में असफल रहा।
terdon

2
टिप्पणी या टिप्पणी करने वाले स्ट्रिंग शाब्दिकों का क्या होना चाहिए? (जैसे INSERT INTO string_table VALUES('/*'), ('*/'), ('/**/');)
जूल

1
संबंधित (क्षमा करें मैं विरोध नहीं कर सकता!): Codegolf.stackexchange.com/questions/48326/…
ilkkachu

मैंने एक और समाधान के साथ अपनी पोस्ट को अपडेट किया, कृपया पुन: जांच करें अगर यह आपके लिए अच्छा है।
लुसियानो अंड्रेस मार्टिनी

जवाबों:


22

मुझे लगता है कि मुझे एक आसान समाधान मिला!

cpp -P yourcommentedfile.txt 

कुछ अद्यतन:

उपयोगकर्ता ilkachu से उद्धरण (उपयोगकर्ता टिप्पणियों से मूल पाठ):

मैंने gcc के विकल्पों के साथ थोड़ा सा खेला: -fpreprocessed अधिकांश निर्देशों और मैक्रो विस्तार (#define और #undef को छोड़कर) को स्पष्ट रूप से अक्षम कर देगा। जोड़ने -dD भी परिभाषित में छोड़ देंगे; और std = c89 का उपयोग नई शैली // टिप्पणियों को अनदेखा करने के लिए किया जा सकता है। यहां तक ​​कि उनके साथ, cpp ने रिक्त स्थान (उन्हें हटाने के बजाय) के साथ टिप्पणियों की जगह ले ली, और रिक्त स्थान और खाली लाइनों को ध्वस्त कर दिया।

लेकिन मुझे लगता है कि यह अभी भी उचित है और अधिकांश मामलों के लिए एक आसान समाधान है, यदि आप मैक्रो विस्तार और अन्य चीजों को अक्षम करते हैं, तो मुझे लगता है कि आपको अच्छे परिणाम मिलेंगे ... - और हां आप इसे बेहतर बनाने के लिए शेल स्क्रिप्ट के साथ जोड़ सकते हैं ... और भी बहुत कुछ...


1
सी प्रीप्रोसेसर का उपयोग करने की संभावना सबसे मजबूत समाधान है। चूंकि प्रीप्रोसेसर संभवतः C टिप्पणियों का सबसे मजबूत पार्सर है। चालाक।
ग्रूम्मल

14
लेकिन cppटिप्पणियों को हटाने की तुलना में बहुत कुछ करेंगे (प्रक्रिया #include, मैक्रोज़ का विस्तार करें, जिसमें
बिलियन

3
@LucianoAndressMartini, नहीं, tail -n +7केवल पहली 7 पंक्तियों को हटा देगा, यह #includeप्रसंस्करण या मैक्रो विस्तार को नहीं रोकेगा । echo __LINE__ | cppउदाहरण के लिए प्रयास करें । याecho '#include /dev/zero' | cpp
स्टीफन चेज़लस

2
-Pयदि आप ऐसा करते हैं तो आप शायद मोड का उपयोग करना चाहते हैं । (यह उपयोग करने की आवश्यकता को समाप्त कर सकता है tail।)
zwol

3
मैंने gcc के विकल्पों के साथ थोड़ा सा खेला: -fpreprocessedअधिकांश निर्देशों और मैक्रो विस्तार (को छोड़कर #defineऔर #undefस्पष्ट रूप से) को अक्षम कर देगा । जोड़ना -dDभी परिभाषित करेगा; और std=c89नई शैली //टिप्पणियों को अनदेखा करने के लिए उपयोग किया जा सकता है । यहां तक ​​कि उनके साथ, cppरिक्त स्थान के बजाय टिप्पणियों को प्रतिस्थापित करता है (उन्हें हटाने के बजाय), और रिक्त स्थान और खाली लाइनों को ढहता है।
इलकाचू

10

मैं एक बार इस के साथ आया था जिसे हम निखार सकते हैं:

perl -0777 -pe '
  BEGIN{
    $bs=qr{(?:\\|\?\?/)};
    $lc=qr{(?:$bs\n|$bs\r\n?)}
  }
  s{
    /$lc*\*.*?\*$lc*/
    | /$lc*/(?:$lc|[^\r\n])*
    | (
         "(?:$bs$lc*.|.)*?"
       | '\''$lc*(?:$bs$lc*(?:\?\?.|.))?(?:\?\?.|.)*?'\''
       | \?\?'\''
       | .[^'\''"/?]*
      )
  }{$1 eq "" ? " " : "$1"}exsg'

कुछ और कोने के मामलों को संभालने के लिए।

नोट यदि आप उस को दूर एक टिप्पणी, आप कोड के अर्थ बदल सकता है ( 1-/* comment */-1जैसे पार्स किया गया है 1 - -1, जबकि 1--1(जो आप अगर आप टिप्पणी हटा प्राप्त चाहते हैं) तो आपको एक त्रुटि देना होगा)। कमेंट को स्पेस कैरेक्टर (जैसा कि हम यहां करते हैं) को पूरी तरह से हटाने के बजाय करना बेहतर है।

उदाहरण के लिए इस मान्य ANSI C कोड पर ठीक से काम करना चाहिए जो कुछ कोने के मामलों को शामिल करने की कोशिश करता है:

# किंकर्तव्यविमूढ़ <stdio.h>
मुख्य प्रवेश बिंदु()
{
  प्रिंटफ ("% d% s% c% c% c% c% c% s% s% d \ n",
  1 - / * टिप्पणी * / - 1,
  / \
* टिप्पणी */
  "/ * टिप्पणी नहीं * /",
  / * बहु
  टिप्पणी */
  '"' /* टिप्पणी */ , '"',
  '\'','"'/* टिप्पणी */,
  '\
\
"', /* टिप्पणी */
  "\\
"/ * टिप्पणी नहीं * /",
  "?? /" / * टिप्पणी नहीं * / ":
  '' '' + '' '' '' * '' टिप्पणी '' /);
  वापसी 0;
}

जो यह आउटपुट देता है:

# किंकर्तव्यविमूढ़ <stdio.h>
मुख्य प्रवेश बिंदु()
{
  प्रिंटफ ("% d% s% c% c% c% c% c% s% s% d \ n",
  1 1,

  "/ * टिप्पणी नहीं * /",

  '' '', '' '',
  '' '', '' ''
  '\
\
" ',  
  "\\
"/ * टिप्पणी नहीं * /",
  "?? /" / * टिप्पणी नहीं * / ":
  '' '' + '' '');
  वापसी 0;
}

संकलित और चलाने पर दोनों एक ही आउटपुट को प्रिंट करते हैं।

आप आउटपुट के साथ तुलना करके gcc -ansi -Eदेख सकते हैं कि प्री-प्रोसेसर उस पर क्या करेगा। यह कोड C99 या C11 कोड भी मान्य है, हालाँकि gccयह डिफ़ॉल्ट रूप से ट्रिग्राफ समर्थन को निष्क्रिय कर देता है , इसलिए यह gccतब तक काम नहीं करेगा जब तक आप मानक को निर्दिष्ट नहीं करते gcc -std=c99या विकल्प को नहीं gcc -std=c11जोड़ते -trigraphs)।

यह इस C99 / C11 (गैर- ANSI / C90) कोड पर भी काम करता है:

// टिप्पणी
/ \
/ टिप्पणी
// मल्टीलाइन \ _
टिप्पणी
"// एक टिप्पणी नहीं"

( gcc -E/ gcc -std=c99 -E/ के साथ तुलना करें gcc -std=c11 -E)

ANSI C ने // formटिप्पणी का समर्थन नहीं किया । //ANSI C में अन्यथा मान्य नहीं है, इसलिए वहां दिखाई नहीं देगा। एक वंचित मामला जहां //वास्तव में एएनएसआई सी में प्रकट हो सकता है (जैसा कि वहां उल्लेख किया गया है , और आप चर्चा के बाकी हिस्सों को दिलचस्प पा सकते हैं) तब होता है जब स्ट्रिंग ऑपरेटर उपयोग में होता है।

यह एक मान्य ANSI C कोड है:

#define s(x) #x
s(//not a comment)

और 2004 में चर्चा के समय, gcc -ansi -Eवास्तव में इसका विस्तार किया "//not a comment"। हालाँकि आज, इस gcc-5.4पर एक त्रुटि देता है, इसलिए मुझे संदेह है कि हम इस तरह के निर्माण का उपयोग करके बहुत सी कोड पाएंगे।

GNU sedसमकक्ष कुछ इस तरह हो सकता है:

lc='([\\%]\n|[\\%]\r\n?)'
sed -zE "
  s/_/_u/g;s/!/_b/g;s/</_l/g;s/>/_r/g;s/:/_c/g;s/;/_s/g;s/@/_a/g;s/%/_p/g;
  s@\?\?/@%@g;s@/$lc*\*@:&@g;s@\*$lc*/@;&@g
  s:/$lc*/:@&:g;s/\?\?'/!/g
  s#:/$lc*\*[^;]*;\*$lc*/|@/$lc*/$lc*|(\"([\\\\%]$lc*.|[^\\\\%\"])*\"|'$lc*([\\\\%]$lc*.)?[^\\\\%']*'|[^'\"@;:]+)#<\5>#g
  s/<>/ /g;s/!/??'/g;s@%@??/@g;s/[<>@:;]//g
  s/_p/%/g;s/_a/@/g;s/_s/;/g;s/_c/:/g;s/_r/>/g;s/_l/</g;s/_b/!/g;s/_u/_/g"

यदि आपका GNU sedसमर्थन करने के लिए बहुत पुराना है -Eया -z, आप पहली पंक्ति को बदल सकते हैं:

sed -r ":1;\$!{N;b1}

इस उत्पादन => गूंज -e "BEGIN / * टिप्पणी * / कमांड / * कॉम \ nment * / अंत" के साथ परीक्षण यह: पर्ल समाधान बहु लाइन के साथ समस्या है
بارپابابا

@ बॉबी, मेरे लिए काम करता है। मैंने अपने परीक्षण मामले में एक बहु-पंक्ति टिप्पणी और परिणामी आउटपुट जोड़ा है।
स्टीफन चेज़लस

आजकल की तुलना में सबसे अच्छी बात यह होगी gcc -std=c11 -E -P( -ansiयह सिर्फ एक और नाम है -std=c90)।
ज़ूल

@zwol, विचार किसी भी C / C ++ मानक (c90, c11 या अन्य) के लिए लिखे गए कोड को संभालने में सक्षम होना है। कड़ाई से बोलना, यह संभव नहीं है (मेरे 2 आकस्मिक उदाहरण देखें)। कोड अभी भी C90 निर्माण (जैसे ??') को संभालने की कोशिश करता है , इसलिए हम cpp -ansiउन लोगों और C99 / C11 के साथ तुलना करते हैं ... एक (जैसे // xxx), इसलिए हम cpp(या cpp -std=c11...) के साथ तुलना करते हैं
स्टीफन चेज़लस

@zwol, मैंने थोड़ा स्पष्ट करने के प्रयास में परीक्षण मामले को विभाजित किया है। ऐसा लग रहा है कि ट्रिगर 11 सी में अभी भी हैं, इसलिए मेरा दूसरा परीक्षण मामला वैसे भी मानक सी नहीं है।
स्टीफन चेज़लस

6

साथ sed:

अपडेट करें

/\/\*/ {
    /\*\// {
        s/\/\*.*\*\///g;
        b next
    };

    :loop;
    /\*\//! {
        N;
        b loop
    };
    /\*\// {
        s/\/\*.*\*\//\n/g
    }
    :next
}

सभी संभव (मल्टी लाइन टिप्पणी, [या] befor के बाद डेटा का समर्थन);

 e1/*comment*/
-------------------
e1/*comment*/e2
-------------------
/*comment*/e2
-------------------
e1/*com
ment*/
-------------------
e1/*com
ment*/e2
-------------------
/*com
ment*/e2
-------------------
e1/*com
1
2
ment*/
-------------------
e1/*com
1
2
ment*/e2
-------------------
/*com
1
2
ment*/e2
-------------------
Daud:
$ sed -f command.sed FILENAME

e1
-------------------
e1e2
-------------------
e2
-------------------
e1

-------------------
e1
e2
-------------------

e2
-------------------
e1

-------------------
e1
e2
-------------------

e2
-------------------

डेटा के बाद शुरू होने वाली टिप्पणी के लिए काम नहीं करेगा, जैसेproc print data 2nd /*another comment is here*/
mazs

@mazs ने अपडेट किया, इसे देखें
بارazابابا

यह स्ट्रिंग शाब्दिक के अंदर टिप्पणियों को संभाल नहीं करता है, जो वास्तव में मायने रखता है, जो कि SQL पर निर्भर करता है
zwol

4
 $ cat file | perl -pe 'BEGIN{$/=undef}s!/\*.+?\*/!!sg'

 proc print data=sashelp.cars;
 run;

 data abc;
 set xyz;
 run;

यदि कोई हो तो रिक्त लाइनें निकालें:

 $ cat file | perl -pe 'BEGIN{$/=undef}s!/\*.+?\*/\n?!!sg'

संपादित करें - स्टीफन द्वारा छोटा संस्करण:

 $ cat file | perl -0777 -pe 's!/\*.*?\*/!!sg'

ठीक है, मैं टेर्डन से सहमत हूं: आओ हम अपेक्षित आउटपुट देखते हैं।
हंस शू

BTW: एक एकल पंक्ति से युक्त क्या होना चाहिए: "/ * foo * / run? / * Bar * /"? चाहिए कि बस "रन;" ?
हंस शू

महान! तब मेरा हल काम करता है। नोट मैं गैर-लालची का उपयोग करता हूं: "+।"
हंस शू

2
इसे -0777करने के लिए एक छोटे तरीके के रूप में देखेंBEGIN{$/=undef}
स्टीफन चेज़लस

1
शायद .*?इसके बजाय .+?अगर /**/एक मान्य टिप्पणी भी है।
२०:०५

2

SED कमांड और कोई स्क्रिप्ट का उपयोग करके समाधान

आप यहाँ हैं:

sed 's/\*\//\n&/g' test | sed '/\/\*/,/\*\//d'

नायब यह ओएस एक्स पर काम नहीं करता है, जब तक आप स्थापित नहीं करते हैं gnu-sed। लेकिन यह लिनक्स डिस्ट्रोस पर काम करता है।


1
आप -iआउटपुट को नई फ़ाइल में पुनर्निर्देशित करने के बजाय फ़ाइल को संपादित करने के लिए विकल्प का उपयोग कर सकते हैं । या -i.bakबैकअप फ़ाइल के लिए अधिक सुरक्षित
राहुल

1
यह सभी मामलों के लिए भी काम नहीं कर रहा है, एक ही लाइन में एक टिप्पणी डालने की कोशिश करें और देखें कि क्या होता है ... उदाहरण सेट xy \; / * परीक्षण * / मुझे लगता है कि हमें perl की आवश्यकता होगी इसे भी आसान तरीके से हल करें।
लुसियानो अंड्रेस मार्टिनी

@ राहुल बिल्कुल, उल्लेख करने के लिए धन्यवाद। मैं बस इसे और सरल रखना चाहता था।
फ़राज़एक्स

मुझे यह कहते हुए बहुत खेद है कि यह एक ही पंक्ति में टिप्पणियों के लिए काम नहीं कर रहा है।
लुसियानो अंड्रेस मार्टिनी

@LucianoAndressMartini अब यह करता है!
FarazX

1

sedएक समय में एक लाइन पर काम करता है, लेकिन इनपुट में कुछ टिप्पणियां कई लाइनों को फैलाती हैं। Https://unix.stackexchange.com/a/152389/90751 के अनुसार , आप पहली बार trलाइन-ब्रेक को किसी अन्य वर्ण में बदलने के लिए उपयोग कर सकते हैं । फिर sedइनपुट को एक पंक्ति के रूप में संसाधित कर सकते हैं, और आप trलाइन-ब्रेक को पुनर्स्थापित करने के लिए फिर से उपयोग करते हैं।

tr '\n' '\0' | sed ... | tr '\0' \n'

मैंने अशक्त बाइट्स का उपयोग किया है, लेकिन आप अपने इनपुट फ़ाइल में दिखाई देने वाले किसी भी वर्ण को चुन सकते हैं।

*नियमित अभिव्यक्तियों में एक विशेष अर्थ है, इसलिए इसे \*शाब्दिक रूप से मिलान करने के लिए भागने की आवश्यकता होगी *

.*है लालची - यह अधिक सहित सबसे लंबे समय तक संभव पाठ से मेल खाएंगे */और /*। इसका मतलब है कि पहली टिप्पणी, अंतिम टिप्पणी और बीच में सब कुछ। इसे प्रतिबंधित करने के लिए, प्रतिस्थापित करें.* एक सख्त पैटर्न के साथ : टिप्पणियों में कुछ भी हो सकता है जो "*" नहीं है, और "*" भी कुछ भी हो सकता है जो "/" नहीं है। कई *एस के रन का भी हिसाब देना होगा:

tr '\n' '\0' | sed -e 's,/\*\([^*]\|\*\+[^*/]\)*\*\+/,,g' | tr '\0' '\n'

यह बहुस्तरीय टिप्पणियों में किसी भी लाइनब्रीक को हटा देगा, अर्थात।

data1 /* multiline
comment */ data2

हो जाएगा

data1  data2

अगर ऐसा नहीं था, तो sed तो लाइनब्रीक में से एक रखने के लिए कहा जा सकता है। इसका मतलब यह है कि एक लाइनब्रेक रिप्लेसमेंट कैरेक्टर को चुना जा सकता है।

tr '\n' '\f' | sed -e 's,/\*\(\(\f\)\|[^*]\|\*\+[^*/]\)*\*\+/,\2,g' | tr '\f' '\n'

विशेष चरित्र \f, और एक बैक-रेफरेंस का उपयोग जो कुछ भी मेल नहीं खा सकता है, सभी sedकार्यान्वयन में इच्छित के रूप में काम करने की गारंटी नहीं है। (मैंने पुष्टि की कि यह GNU sed 4.07 और 4.2.2 पर काम करता है।)


क्या आप बता सकते हैं कि यह कैसे काम करेगा। tr '\ n' '\ 0' | sed -e's, / * ([^ *] \ _ * + + [^ * /]) ** \ + / ,, जी 'test.sas | tr '\ 0' '\ n' और मैं नीचे मिला: / * यह आउटपुट डेटा प्रिंट करना है * / डेटा abcdf; सेट cfgtr; Daud; खरीद प्रिंट डेटा = sashelp.cars; Daud; डेटा एबीसी; xyz सेट करें; Daud;
शैरिक आलम

@ShariqueAlam आपने test.sasवहां पाइप लाइन के बीच में रखा है, इसलिए sedइसे सीधे से पढ़ता है, और पहले trका कोई प्रभाव नहीं है। आपको उपयोग करने की आवश्यकता हैcat test.sas | tr ...
JigglyNaga

0

टिप्पणियों को हटाने के लिए एक पंक्ति सेड का उपयोग करना:

sed '/\/\*/d;/\*\//d' file

proc print data=sashelp.cars;
run;
data abc;
set xyz;
run;
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.