2013-09-22 8 views
7

Chcę wyodrębnić wiersze, które nie zawierają # i usunąć ", ; w danych wyjściowych.Awk: Korzystanie z dopasowania odwrotnego do ciągu znaków, a następnie podstawianie znaków

mój plik wejściowy wygląda następująco:

# ;string"1" 
# string"2"; 
string"3"; 

można użyć grep i tr dostać chciał wyjściowe:

grep -v '#' FILE | tr -d ';"' 
string3 

Jednak chcę użyć awk.

można wyodrębnić inwertowanym mecz awk '!/#/' FILE, ale w jaki sposób mogę korzystać sub usunąć ", ; w tym samym poleceniu awk?

Odpowiedz

5

Można użyć gsub globalnego podstawienia:

awk '!/#/{gsub(/[";]/,"",$0);print}' 

Poniższy zapis pokazuje to w działaniu, to jest dostawcą takie same wyniki, jak Twój rurociąg grep/tr:

pax> echo '# ;string"1" 
# string"2"; 
string"3";' | awk '!/#/{gsub(/[";]/,"",$0);print}{}' 

string3 

Należy pamiętać, że ostateczny kod {} może nie być konieczny w niektórych implementacjach awk, ale jest tam, aby zatrzymać wyjście niezgodnych linii w tych implementacjach (zwykle starszych), które robią to automatycznie dla linii nie pasujących do żadnej z reguł.

+0

+1 dla właściwego podejścia. Nie potrzebujesz argusa '$ 0' w' gsub() ', ponieważ jest to ustawienie domyślne. –

3

Zastosowanie gsub zamiast które mogłyby zastąpić wszystko nie pasuje tylko jedno:

awk '/#/{next}{gsub(/[";]/,"")}1' file 

wyjściowa:

string3 
  • Pomijanie trzeci parametr do gsub sprawia, że ​​przetwarzanie $0 domyślnie.
  • /#/{next} czyni go pominąć linie zawierające #
  • 1 sprawia, że ​​drukowanie $0
+0

Jeśli wykonaj 'gsub' przed testem na to, co linia do druku, nie trzeba "następny". Zobacz mój wpis "Kolejna wersja awk". Dlaczego masz ',' w ramach '[",;] '? Nie było go w żądaniu, aby go zastąpić, więc można go usunąć – Jotne

+1

@Jotne Złożoność nadal byłaby taka sama i jeszcze bardziej złożona, ponieważ" d zmodyfikuj ogólnie separator globalny, a nawet użyj 'OFS ='.Ponadto, będziesz miał więcej przetwarzania przy użyciu gsub najpierw przed wykluczeniem skomentowanej linii, ponieważ to przetwarzałoby linię, która nie jest już potrzebna. I to jest właśnie powód, dla którego tego nie zrobiłem. Dzięki, przy okazji. Zrobiłem aktualizację. – konsolebox

+0

+1 do przełączania na logikę dodatnią ('pomiń linie zawierające #' zamiast 'wybierz linie, które NIE zawierają #'), a więc skłaniają skrypt do zmniejszania podwójnych negatywów, jeśli zostaną ulepszone w przyszłości. Prawdopodobnie jest to przesada, ale ogólna koncepcja próby pozytywnego działania jest zazwyczaj dobra. OP powiedział "linie ZAWIERAJĄCE #", nie tylko linie zaczynające się od '# ', więc możesz usunąć'^'. –

2

Innym awk wersja

awk -F"[\";]" '{$1=$1} !/^#/' OFS= file 
string3 

awk '{gsub(/[";]/,x)} !/^#/' file 
string3 

x oznacza nic. Mógł również stosować "", ale ratuje jedno znaki :)

2

Jeśli chcesz dać sed szansę:

sed -n '/^[^#]/s/[";]//gp' file 
string3