Próbowałem sed i awk, ale to nie działa, ponieważ postać zawiera „/”, który jest już w dowodzie jako separator.
Daj mi znać, jak mogę to osiągnąć.
Poniżej znajduje się przykładowy przykład. Chcemy usunąć skomentowane sekcje, tj /*.....*/
/*This is to print the output
data*/
proc print data=sashelp.cars;
run;
/*Creating dataset*/
data abc;
set xyz;
run;
text-processing
Sharique Alam
źródło
źródło
INSERT INTO string_table VALUES('/*'), ('*/'), ('/**/');
)Odpowiedzi:
Myślę, że znalazłem łatwe rozwiązanie!
NIEKTÓRE AKTUALIZACJE:
Cytat od użytkownika ilkachu (oryginalny tekst z komentarzy użytkownika):
Grałem trochę z opcjami gcc: -fpreprocessor wyłączy większość dyrektyw i rozszerzeń makr (z wyjątkiem #define i #undef najwyraźniej). Dodanie -dD spowoduje także pozostawienie definicji; a std = c89 może być użyte do zignorowania nowego stylu // komentarzy. Nawet przy nich cpp zastępuje komentarze spacjami (zamiast je usuwać) i zwija spacje i puste linie.
Ale myślę, że nadal jest rozsądne i łatwe rozwiązanie w większości przypadków, jeśli wyłączysz rozwijanie makr i inne rzeczy, myślę, że uzyskasz dobre wyniki ... - i tak, możesz połączyć to ze skryptem powłoki, aby uzyskać lepsze ... i wiele więcej...
źródło
cpp
zrobi o wiele więcej niż usuwanie komentarzy (przetwarzanie#include
, rozwijanie makr, w tym wbudowanych ...)tail -n +7
po prostu usunie pierwsze 7 wierszy, nie zapobiegnie#include
przetwarzaniu ani rozwinięciom makr. Spróbujecho __LINE__ | cpp
na przykład. Lubecho '#include /dev/zero' | cpp
-P
trybu, jeśli to zrobisz. (Może to wyeliminować potrzebę używaniatail
.)-fpreprocessed
wyłączy większość dyrektyw i rozszerzeń makr (z wyjątkiem#define
i#undef
najwyraźniej). Dodanie-dD
pozostawi również definicje; istd=c89
może służyć do ignorowania//
komentarzy w nowym stylu . Nawet z nimicpp
zastępuje komentarze spacjami (zamiast je usuwać) i zwija spacje i puste linie.Kiedyś wpadłem na pomysł, który możemy udoskonalić:
aby obsłużyć jeszcze kilka skrzynek narożnych
Zauważ, że jeśli usuniesz komentarz, możesz zmienić znaczenie kodu (
1-/* comment */-1
parsowane jak1 - -1
podczas while1--1
(które uzyskasz , jeśli usuniesz komentarz) spowoduje błąd). Lepiej zastąpić komentarz spacją (tak jak tutaj), zamiast całkowicie go usunąć.Powyższe powinno działać poprawnie na tym poprawnym kodzie ANSI C, na przykład, który próbuje uwzględnić kilka przypadków narożnych:
Co daje ten wynik:
Oba drukują ten sam wynik po kompilacji i uruchomieniu.
Możesz porównać z wyjściem,
gcc -ansi -E
aby zobaczyć, co zrobiłby na nim procesor wstępny. Ten kod jest również prawidłowym kodem C99 lub C11, jednakgcc
domyślnie wyłącza obsługę trigrafów, więc nie będzie działać,gcc
chyba że określisz standard,gcc -std=c99
lubgcc -std=c11
lub dodasz-trigraphs
opcję).Działa również z tym kodem C99 / C11 (nie ANSI / C90):
(porównaj z
gcc -E
/gcc -std=c99 -E
/gcc -std=c11 -E
)ANSI C nie obsługiwał
// form
komentarza.//
nie jest inaczej ważne w ANSI C, więc nie pojawi się tam. Jednym z wymyślonych przypadków, w których//
może rzeczywiście pojawić się w ANSI C (jak tam wspomniano , a resztę dyskusji może okazać się interesująca), jest użycie operatora strunizacji .To jest poprawny kod ANSI C:
I w czasie dyskusji w 2004 r.
gcc -ansi -E
Rzeczywiście ją rozszerzyłem"//not a comment"
. Jednak dzisiajgcc-5.4
zwraca błąd, więc wątpię, abyśmy znaleźli dużo kodu C przy użyciu tego rodzaju konstrukcji.Odpowiednikiem GNU
sed
może być coś takiego:Jeśli GNU
sed
jest zbyt stary, by wspierać-E
lub-z
można wymienić pierwszą linię z:źródło
gcc -std=c11 -E -P
(-ansi
to po prostu inna nazwa-std=c90
).??'
), dlatego porównujemy zcpp -ansi
tymi i C99 / C11 ... jeden (jak// xxx
), dlatego porównujemy zcpp
(lubcpp -std=c11
...)z
sed
:AKTUALIZACJA
obsługuje wszystkie możliwe (komentarz wieloliniowy, dane po [lub] przed,);
biegać:źródło
proc print data 2nd /*another comment is here*/
Usuń puste linie, jeśli występują:
Edycja - krótsza wersja Stephane:
źródło
-0777
krótszy sposóbBEGIN{$/=undef}
.*?
zamiast.+?
jeśli/**/
jest to również poprawny komentarz.Rozwiązanie za pomocą polecenia SED i bez skryptu
Tu masz:
sed 's/\*\//\n&/g' test | sed '/\/\*/,/\*\//d'
Uwaga: To nie działa w systemie OS X, chyba że zainstalujesz
gnu-sed
. Ale działa na Linux Distros.źródło
-i
opcji edycji pliku w miejscu zamiast przekierowywania wyjścia do nowego pliku. lub znacznie bezpieczniejsze-i.bak
tworzenie kopii zapasowej plikused
działa na jednej linii na raz, ale niektóre komentarze na wejściu obejmują wiele linii. Zgodnie z /unix//a/152389/90751 , możesz najpierw użyć,tr
aby zmienić łamanie linii w inną postać. Następniesed
możesz przetworzyć dane wejściowe jako pojedynczą linię i użyćtr
ponownie, aby przywrócić podział linii.Użyłem bajtów zerowych, ale możesz wybrać dowolny znak, który nie pojawia się w pliku wejściowym.
*
ma specjalne znaczenie w wyrażeniach regularnych, więc będzie musiał uciekać,\*
aby dopasować literał*
..*
jest chciwy - będzie pasował do jak najdłuższego tekstu, w tym więcej*/
i/*
. To oznacza pierwszy komentarz, ostatni komentarz i wszystko pomiędzy. Aby to ograniczyć, zamień.*
na bardziej rygorystyczny wzorzec: komentarze mogą zawierać wszystko, co nie jest „*”, a także „*”, a po nim wszystko, co nie jest „/”. W przypadku wielu serii należy*
również uwzględnić:Spowoduje to usunięcie wszelkich podziałów wiersza w komentarzach wielowierszowych, tj.
stanie się
Jeśli nie tego chciał,
sed
można powiedzieć, że zachowa jeden z przełomów. Oznacza to wybranie znaku zastępującego podział linii, który można dopasować.Nie
\f
można zagwarantować, że specjalny charakter i użycie odnośnika wstecznego, który może nic nie pasował, we wszystkichsed
implementacjach. (Potwierdziłem, że działa na GNU sed 4.07 i 4.2.2.)źródło
test.sas
w środku rurociągu, więcsed
czyta z niego bezpośrednio, a pierwszytr
nie ma wpływu. Musisz użyćcat test.sas | tr ...
za pomocą jednej linii sed do usunięcia komentarzy:
źródło