/ *… * / / * & * / Dahil tüm karakterleri nasıl silebilirim?


12

Ben sed ve awk denedim, ama karakter olarak çalışmayan zaten sınırlayıcı olarak komut var "/" içerir.

Lütfen bunu nasıl başarabileceğimi bana bildirin.

Aşağıda örnek bir örnek verilmiştir. Yorumlanan bölümleri kaldırmak istiyoruz. /*.....*/

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

-bash-4.1 $ sed 's, / *. ** / ,, g' test.sas Aşağıda aldığım çıkış var, ilk yorum hala orada. / * Bu çıktı verilerini yazdırmak içindir * / proc baskı verileri = sashelp.cars; Çalıştırmak; veri abc; set xyz; Çalıştırmak;
Sharique Alam

1
Düzenleme için teşekkürler. İstediğiniz çıktıyı da dahil etseniz daha da iyi olurdu. Ayrıca ne denediğinizi ve sorunun nasıl başarısız olduğunu yorumlara dahil etmeyin.
terdon

2
Yorum veya yorum sınırlayıcı içeren dizgi değişmezlerine ne olur? (örn. INSERT INTO string_table VALUES('/*'), ('*/'), ('/**/');)
zwol

1
İlgili (üzgünüm dayanamıyorum
ilkkachu

Yazımı başka bir çözümle güncelledim, lütfen şimdi sizin için iyi olup olmadığını tekrar kontrol edin.
Luciano Andress Martini

Yanıtlar:


22

Bence kolay bir çözüm buldum!

cpp -P yourcommentedfile.txt 

BAZI GÜNCELLEMELER:

Kullanıcının alıntısı ilkachu (kullanıcı yorumlarından orijinal metin):

Ben gcc seçenekleri ile biraz oynadı: -fpreprocessed çoğu yönergeleri ve makro genişletmeleri devre dışı bırakacaktır (#define ve #undef görünüşte hariç). -DD eklenmesi de tanımları bırakacaktır; ve std = c89 yeni stil // yorumlarını yoksaymak için kullanılabilir. Onlarla bile, cpp yorumları boşluklarla (yerine kaldırmak yerine) değiştirir ve boşlukları ve boş satırları daraltır.

Ancak, makro genişlemeyi ve diğer şeyleri devre dışı bırakırsanız, iyi sonuçlar alacağınızı düşünüyorum ... - ve evet, daha iyi olması için bunu kabuk komut dosyasıyla birleştirebilirsiniz. ... ve daha fazlası...


1
C ön işlemcisinin kullanılması muhtemelen en sağlam çözümdür. Önişlemci muhtemelen C yorumlarının en sağlam ayrıştırıcısı olduğundan. Zeki.
grochmal

14
Ancak cppyorumları kaldırmaktan çok daha fazlasını yapacak (süreç #include, yerleşik olanlar dahil makroları genişlet ...)
Stéphane Chazelas

3
@ LucianoAndressMartini, hayır, tail -n +7sadece ilk 7 satırı kaldıracak, #includeişleme veya makro genişletmelerini engellemeyecek . echo __LINE__ | cppÖrneğin deneyin . Veyaecho '#include /dev/zero' | cpp
Stéphane Chazelas

2
Bunu -Pyaparsanız muhtemelen modu kullanmak istersiniz . (Bu, kullanma gereğini ortadan kaldırabilir tail.)
zwol

3
Ben gcc seçenekleri ile biraz oynadı: -fpreprocessedçoğu direktifleri ve makro genişletmelerini devre dışı bırakacaktır ( görünüşte #defineve hariç #undef). Ekleme -dDde tanımları bırakacaktır; ve std=c89yeni stil //yorumlarını yok saymak için kullanılabilir . Onlarla bile, cppyorumları boşluklarla değiştirir (kaldırmak yerine) ve boşlukları ve boş satırları daraltır.
ilkkachu

10

Bir keresinde ile geldi bu biz hassaslaştırmalarına:

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'

birkaç köşe davasını ele almak için.

Eğer varsa o Not kaldırmak bir yorum, kod anlam değiştirebilir ( 1-/* comment */-1gibi ayrıştırılır 1 - -1iken 1--1(Yorumunuzu kaldırıldı eğer elde ederim), hata verebilir olacaktır). Yorumu tamamen kaldırmak yerine boşluk karakteriyle (burada yaptığımız gibi) değiştirmek daha iyidir.

Yukarıdakiler, örneğin birkaç köşe vakası eklemeye çalışan bu geçerli ANSI C kodunda düzgün çalışmalıdır:

#include <stdio.h>
int main ()
{
  printf ("% d% s% c% c% c% c% c% s% s% d \ n",
  1 - / * yorum * / - 1,
  / \
* yorum Yap */
  "/ * yorum değil * /",
  / * çok satırlı
  yorum Yap */
  '"' /* yorum Yap */ , '"',
  '\'','"'/* yorum Yap */,
  '\
\
"', /* yorum Yap */
  "\\
"/ * yorum değil * /",
  "?? /" / * yorum değil * / ",
  '??' '+' '' / * "yorum" * /);
  dönüş 0;
}

Bu çıktıyı verir:

#include <stdio.h>
int main ()
{
  printf ("% d% s% c% c% c% c% c% s% s% d \ n",
  1- -1,

  "/ * yorum değil * /",

  '"', '"',
  '\' ',' "',
  '\
\
"',  
  "\\
"/ * yorum değil * /",
  "?? /" / * yorum değil * / ",
  '??' '+' "');
  dönüş 0;
}

Her ikisi de derlendiğinde ve çalıştırıldığında aynı çıktıyı yazdırır.

gcc -ansi -EÖn işlemcinin üzerinde ne yapacağını görmek için çıktı ile karşılaştırabilirsiniz . Bu kod, ancak aynı zamanda geçerli C99 veya C11 kodudur gccüç karakterli varsayılan olarak destekleyen devre dışı bırakır böylece olmaz ile iş gccsizin gibi standart belirtmek sürece gcc -std=c99veya gcc -std=c11veya ekleme -trigraphs) seçeneği.

Ayrıca bu C99 / C11 (ANSI / C90 olmayan) kod üzerinde çalışır:

// yorum Yap
/ \
/ yorum Yap
// çok satırlı \
yorum Yap
"// yorum değil"

( gcc -E/ gcc -std=c99 -E/ ile karşılaştır gcc -std=c11 -E)

ANSI C // formyorumu desteklemedi . //ANSI C'de başka şekilde geçerli olmadığından orada görünmez. Bir yapmacık durum nereye //(belirtildiği gibi gerçekten ANSI C görünebilir orada ve tartışma ilginç kalanını bulabilirsiniz) ne zaman olduğu stringify operatör kullanılıyor.

Bu geçerli bir ANSI C kodudur:

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

Ve 2004'teki tartışma sırasında gcc -ansi -Ebunu gerçekten genişletti "//not a comment". Ancak bugün, gcc-5.4üzerinde bir hata döndürür, bu yüzden bu tür bir yapı kullanarak C kodu bir sürü bulacağımızdan şüpheliyim.

GNU sedeşdeğeri şöyle bir şey olabilir:

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'nuz seddesteklenemeyecek kadar eskiyse -Eveya -zilk satırı şu şekilde değiştirebilirsiniz:

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

perl çözümü çok satır ile sorun var: bu çıktı ile test => echo -e "BEGIN / * yorum * / KOMUT / * com \ nment * / END"
بارپابابا

@Babby, benim için çalışıyor. Test durumuma çok satırlı bir yorum ve sonuç çıktısı ekledim.
Stéphane Chazelas

Bugünlerde karşılaştırmak için en iyi şey olurdu gcc -std=c11 -E -P( -ansisadece başka bir isim -std=c90).
zwol

@zwol, fikir herhangi bir C / C ++ standardı (c90, c11 veya diğer) için yazılan kodu işleyebilmektir. Kesin olarak söylemek gerekirse, bu mümkün değil (2. anlaşmalı örneğime bakın). Kod hala C90 yapılarını (örneğin ??') ele almaya çalışır , bu nedenle cpp -ansi// xxxcppcpp -std=c11
bunlar

@zwol, test durumunu biraz açıklığa kavuşturmak için böldüm. Trigraflar hala C11'de gibi görünüyor, bu yüzden ikinci test durumum zaten standart C değil.
Stéphane Chazelas

6

ile sed:

GÜNCELLEME

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

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

mümkün olan her şeyi destekleyin (çok satırlı yorum, [veya ve sonrası] sonrası veriler;

 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
-------------------
Çalıştırmak:
$ sed -f command.sed FILENAME

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

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

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

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

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

proc print data 2nd /*another comment is here*/
Verilerden

@mazs güncellendi, kontrol et
بارپابابا

Bu, SQL'in ne yaptığına bağlı olarak, gerçekten önemli olabilecek dize değişmezlerinin içindeki yorumları işlemez
zwol

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

 proc print data=sashelp.cars;
 run;

 data abc;
 set xyz;
 run;

Varsa boş satırları kaldırın:

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

Düzenle - Stephane'nin daha kısa versiyonu:

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

terdon ile hemfikirim: Beklenen çıktıyı görelim.
Hans Schou

BTW: "/ * foo * / run; / * bar * /" içeren tek bir satıra ne olmalı? Bu sadece "koşmak" olmalıdır; ?
Hans Schou

Harika! Sonra benim çözümüm işe yarıyor. Not Açgözlü olmayan kullanıyorum: ". +?"
Hans Schou

2
Daha -0777kısa bir yol olarak görünBEGIN{$/=undef}
Stéphane Chazelas

1
Belki .*?yerine .+?eğer /**/geçerli bir yorum çok olduğunu.
ilkkachu

2

Komut Dosyası Kullanmadan SED komutunu kullanarak çözüm

Buyrun:

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

Not Bu, yüklemediğiniz sürece OS X üzerinde çalışmaz gnu-sed. Ancak Linux Distros üzerinde çalışır.


1
-içıktıyı yeni dosyaya yeniden yönlendirmek yerine dosyayı yerinde düzenleme seçeneğini kullanabilirsiniz . veya -i.bakyedekleme dosyasına çok daha güvenli
Rahul

1
Tüm durumlar için de işe yaramıyor, aynı satıra bir yorum koymaya ve neler olduğunu izlemeye çalışın ... Örnek set xy \; / * test * / Bence perl de bunu kolay bir şekilde çözeceğiz.
Luciano Andress Martini

@Rahul tam olarak, bahsettiğiniz için teşekkürler. Sadece daha basit tutmak istedim.
FarazX

Aynı satırdaki yorumlar için çalışmadığını söylediğim için çok üzgünüm.
Luciano Andress Martini

@LucianoAndressMartini Şimdi öyle!
FarazX

1

sedbir kerede bir satırda çalışır, ancak girişteki yorumların bazıları birden çok satıra yayılır. Https://unix.stackexchange.com/a/152389/90751 uyarınca , ilk önce trsatır sonlarını başka bir karaktere dönüştürmek için kullanabilirsiniz . Sonra sedgirişi tek bir satır olarak işleyebilir trve satır sonlarını geri yüklemek için tekrar kullanırsınız.

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

Boş bayt kullandım, ancak giriş dosyanızda görünmeyen herhangi bir karakteri seçebilirsiniz.

*düzenli ifadelerde özel bir anlamı vardır, bu yüzden \*bir değişmez kelimeyle eşleşecek şekilde kaçmak gerekir *.

.*olan açgözlü - bu daha fazlasını içeren en uzun olası metin, maç olacak */ve /*. Bu, ilk yorum, son yorum ve aradaki her şey anlamına gelir. Bunu kısıtlamak için, .*daha katı bir kalıpla değiştirin : yorumlar, "*" olmayan bir öğeyi ve ardından "*" ve ardından "/" olmayan bir öğeyi içerebilir. Birden ait çalıştırır *ler de hesaba katılacaktır vardır:

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

Bu, çok satırlı yorumlardaki satır satırlarını kaldıracaktır;

data1 /* multiline
comment */ data2

Olacak

data1  data2

İstenilen bu değilse sed, çizgi çizgilerinden birini tutması söylenebilir. Bu, eşleştirilebilen bir satır sonu değiştirme karakteri seçmek anlamına gelir.

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

Özel karakter \fve herhangi bir şeyle eşleşmemiş olabilecek bir geri referansın kullanılması, tüm seduygulamalarda amaçlandığı gibi çalışacağı garanti edilmez . (GNU sed 4.07 ve 4.2.2 üzerinde çalıştığını doğruladım.)


Lütfen nasıl çalışacağını bana bildirir misiniz.Aşağıdaki gibi denedim. tr '\ n' '\ 0' | sed -e 's, / * ([^ *] \ | * \ + [^ * /]) ** \ + / ,, g' Instagram Hesabındaki Resim ve Videoları test.sas | tr '\ 0' '\ n' ve ben aşağıdaki gibi var: / * Bu çıktı verilerini yazdırmak için * / data abcdf; set cfgtr; Çalıştırmak; proc baskı verileri = sashelp.cars; Çalıştırmak; veri abc; set xyz; Çalıştırmak;
Sharique Alam

@ShariqueAlam test.sasOrada boru hattının ortasına koydunuz , bu yüzden seddoğrudan okuyor ve ilkinin bir tretkisi yok. Kullanmanız gerekiyorcat test.sas | tr ...
JigglyNaga

0

yorumları kaldırmak için bir satır sed kullanma:

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

proc print data=sashelp.cars;
run;
data abc;
set xyz;
run;
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.