Jak uniknąć pojedynczego cudzysłowu w awk


111

Chcę wykonać następujące czynności

awk 'BEGIN {FS=" ";} {printf "'%s' ", $1}'

Ale unikanie pojedynczego cudzysłowu w ten sposób nie działa

awk 'BEGIN {FS=" ";} {printf "\'%s\' ", $1}'

Jak to zrobić? Dzięki za pomoc.


Wiele języków wymyka się cudzysłowom, umieszczając dwa z nich pod rząd, może spróbuj.
joshuahealy

Próbowałem awk 'BEGIN {FS = "";} {printf "' '% s' '", $ 1}', ale żaden pojedynczy cudzysłów nie został wydrukowany.

Ta Strona mówi, że włączenie pojedynczego cudzysłowu do pojedynczego cudzysłowu jest niemożliwe. Może będziesz musiał zamienić na podwójne cudzysłowy.
joshuahealy

2
Jest to niemożliwe, ale dwa sąsiadujące ze sobą ciągi muszelek w pojedynczych cudzysłowach sklejają się w jeden parametr. A dwa ciągi powłoki w pojedynczych cudzysłowach sklejone znakami niebędącymi białymi znakami również wklejają się w jedną dużą glob: 'abc'd'ef'is abcdef: literal plus dplus literal. dJest poza cudzysłowów, można wymienić, że dto ze \'aby 'abc'\''ef'rozpoznawaną abc'ef.
Kaz

Odpowiedzi:


160

To może to, czego szukasz:

awk 'BEGIN {FS=" ";} {printf "'\''%s'\'' ", $1}'

Oznacza to, '\''że zamknij otwór ', a następnie wydrukuj literał ', uciekając z niego, a na koniec otwórz 'ponownie.


48
Nie ma to nic wspólnego z awk. 'Charakter zamyka otwór 'dosłownym powłoki ciąg. Literał powłoki nie obsługuje w tym celu znaku ucieczki z ukośnikiem odwrotnym. Sekwencja '\''załatwia sprawę: to zamyka apostrofu dosłownego, określa znak cudzysłowu (używając ucieczkę który jest obsługiwany poza literałów apostrofu), a następnie ponownie otwiera nowy singiel-cytat dosłowny. Możesz myśleć o tym jako o czteroznakowej sekwencji ucieczki, aby uzyskać pojedynczy cytat. :)
Kaz

2
@Steve: Wielkie dzięki za bardzo przydatną odpowiedź. Uratowałeś mi wiele bólów głowy!
John Slegers,

4
@syntaxerror To, jakich cudzysłowów używasz do przygotowywania argumentów do wywołania, awkzależy wyłącznie od interpretera poleceń, którego używasz do tworzenia wierszy poleceń. '{printf $2}'Zostaje przekształcony jakiegoś argumentu w execvewywołaniu systemowym lub podobnych, gdzie to właśnie wygląda null zakończone C ciąg bez żadnych apostrofami. Awk nigdy nie widzi cytatów, sed. Można w rzeczywistości używać podwójnych cudzysłowów, ale cudzysłowy nie uniemożliwiają ekspansję powłoce z dnia $2, więc trzeba uciec znak dolara z odwrotnym ukośnikiem, aby to dosłowne: "{printf \$2}".
Kaz,

4
@syntaxerror Zwyczajowo, wbudowany skrypt awk jest zwykle poprzedzany pojedynczymi cudzysłowami, ponieważ składnia awk często zawiera elementy leksykalne, które są specjalne dla powłoki, takie jak podwójne cudzysłowy ciągów znaków i pola numerowane oznaczone znakami dolara. Jeśli wyrażenie regularne sed (lub cokolwiek innego) zawiera składnię powłoki, również musisz być ostrożny. sed -e "s/$FOO/$BAR/"nie będzie działać, jeśli intencją jest zastąpienie dosłownego tekstu $FOOz $BAR. Najprościej byłoby sed -e 's/$FOO/$BAR/.
Kaz,

1
@syntaxerror Jeśli umieścisz programy awk w podwójnych cudzysłowach, napotkasz wiele znaków ucieczki, na przykład awk "{ print \"abc\", \$1 }". Za każdym razem, gdy w programie awk pojawia się cudzysłów, należy go zmienić, aby nie zamykał cudzysłowu powłoki. I porównaj to: awk '{print "\\"}'(wypisz odwrotny ukośnik) z tym, co trzeba zrobić z podwójnymi cudzysłowami awk "BEGIN {print \"\\\\\" }":, Uff! Należy pominąć oba cudzysłowy i oba ukośniki odwrotne. Powłoka konwertuje \\ do, \ więc musimy \\\\ kodować \\ .
Kaz

76

Pojedynczy cytat jest reprezentowany za pomocą \x27

Jak w

awk 'BEGIN {FS=" ";} {printf "\x27%s\x27 ", $1}'

Źródło


16
+1, ale trzeba dodać: \x27to rozszerzenie; POSIX Awk rozpoznaje tylko pliki \047. (też \47jest ok, jeśli nie następuje cyfra ósemkowa).
hemflit

1
Jak zakończysz \ x27, jeśli masz po nim kolejny numer?
Jason Axelson

1
Jason, łączysz dwa literały ciągów: "AAA \ x27" "1". Lub po prostu użyj ósemkowego.
hemflit

9
Zawsze używaj ósemkowej ( \047), a nie hex ( \x27), kodów ucieczki - zobacz awk.freeshell.org/PrintASingleQuote .
Ed Morton

35

Inną opcją jest przekazanie pojedynczego cudzysłowu jako zmiennej awk :

awk -v q=\' 'BEGIN {FS=" ";} {printf "%s%s%s ", q, $1, q}'

Prostszy przykład z konkatenacją ciągów:

# Prints 'test me', *including* the single quotes.
$ awk -v q=\' '{print q $0 q }' <<<'test me'
'test me'

5
Jest to jasne i zwięzłe, zwłaszcza jeśli musisz użyć wielu cytatów.
Peter Gluck

18
awk 'BEGIN {FS=" "} {printf "\047%s\047 ", $1}'

1
Tak długo, jak pamiętam, że \047jest to ósemkowa sekwencja ucieczki dla znaku pojedynczego cudzysłowu, ta alternatywa jest dla mnie najbardziej czytelna.
Anthony Geoghegan

4

W przypadku małych skryptów opcjonalnym sposobem uczynienia go czytelnym jest użycie zmiennej takiej jak ta:

awk -v fmt="'%s'\n" '{printf fmt, $1}'

Znalazłem to wygodne w przypadku, gdy musiałem wielokrotnie tworzyć pojedynczy cudzysłów w wyniku, a \ 047 sprawiały, że był on całkowicie nieczytelny

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.