[英]RS in awk language
我正在學習awk編程語言,並且在這里遇到了問題。
我有一個文件(awk.dat),具有以下內容:
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Maecenas pellentesque erat vel tortor consectetur condimentum.
Nunc enim orci, euismod id nisi eget, interdum cursus ex.
Curabitur a dapibus tellus.
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Aliquam interdum mauris volutpat nisl placerat, et facilisis.
我正在使用以下命令:
awk 'BEGIN{RS="*, *";ORS="<<<---\n"} {print $0}' awk.dat
返回錯誤:
awk: run time error: regular expression compile failed (missing operand)
*, *
FILENAME="" FNR=0 NR=0
同時,如果我使用以下命令: awk 'BEGIN{RS=" *, *";ORS="<<<---\\n"} {print $0}' awk.dat
,它給了我所需的結果。
我需要了解這一部分: RS=" *, *"
,雙引號之間的空間的意義*
之前,
由於它的投擲的錯誤。
預期產量:
Lorem ipsum dolor sit amet<<<---
consectetur adipiscing elit.
Maecenas pellentesque erat vel tortor consectetur condimentum.
Nunc enim orci<<<---
euismod id nisi eget<<<---
interdum cursus ex.
Curabitur a dapibus tellus.
Lorem ipsum dolor sit amet<<<---
consectetur adipiscing elit.
Aliquam interdum mauris volutpat nisl placerat<<<---
et facilisis.
<<<---
謝謝。
"[space1]*,[space2]*"
是一個正則表達式,它與以下字符串匹配:
零個或多個空格(space1),后跟一個逗號,然后是零個或多個空格(space2)
第一個"*,[space]*"
是錯誤的,因為*
在正則表達式中具有特殊含義。 這意味着將匹配的組/字符重復零次或多次。 您不能一開始就將其放置。
請注意,根據POSIX, RS
被定義為單個字符而不是正則表達式。
RS
字符串值的第一個字符應為輸入記錄分隔符; 默認情況下為<newline>。 如果RS
包含多個字符,則結果不確定。 如果RS
為空,則記錄由由<newline>加上一個或多個空行組成的序列分隔,開頭或結尾的空行在輸入的開頭或結尾不應導致空記錄,而<newline>應不管FS
的值是多少,始終是字段分隔符。來源: Awk Posix標准
這意味着RS=" *, *"
導致未定義的行為 。
實現POSIX擴展的其他版本的awk,對於RS
含義可能有不同的方法。 例如GNU awk和mawk。 兩者都將RS
實現為正則表達式,但是兩種實現都略有不同。 <asterisk>用法的摘要如下:
| RS | awk (posix) | gawk | mawk |
|------+--------------+------------------+------------------|
| "*" | "<asterisk>" | "<asterisk>" | "<asterisk>" |
| "*c" | undefined | "<asterisk>c" | undefined |
| "c*" | undefined | "","c","ccc",... | "","c","ccc",... |
c is any character
上面應該解釋OP的錯誤,因為根據mawk RS="*, *"
是無效的正則表達式。
$ echo "abc" | ./mawk '/*c/'
mawk: line 1: regular expression compile failed (missing operand)
GNU awk:GNU awk的手冊規定如下:
使用
gawk
,RS
的值不限於一個字符的字符串。 它可以是任何正則表達式 (請參閱Regexp )。 (ce)通常,每條記錄在與正則表達式匹配的下一個字符串處結束; 下一條記錄從匹配字符串的末尾開始。來源: GNU awk手冊
為了了解<asterisk>在GNU awk中的正則表達式中的用法,我們發現:
<星號>
*
此符號表示前面的正則表達式應重復多次以找到匹配項。 例如,ph*
將*
符號應用於前面的h
並查找一個p
匹配項,后跟任意數量的h
s。 如果不存在h
則也僅匹配p
。要了解
*
工作原理,有兩點要*
。 首先,*
僅適用於單個前面的正則表達式分量(例如,在ph*
,它僅適用於h
)。 要使*
應用於較大的子表達式,請使用括號:(ph)*
匹配ph
,phph
,phphph
等。其次,
*
查找盡可能多的重復。 如果要匹配的文本是phhhhhhhhhhhhhhooey
,則ph*
匹配所有h
s。來源: GNU正則表達式運算符
但必須指出的是:
在
POSIX awk和gawk中,*
,+
和?
當正則表達式中沒有任何運算符時,運算符將代表自己。 例如,/+/
匹配文字加號。 但是,awk的許多其他版本將這種用法視為語法錯誤。來源: GNU正則表達式運算符
因此,設置RS="*, *"
意味着它將與字符串"*,"
, "*, "
, "*, "
,...相匹配。
$ echo "a,b, c" | awk 'BEGIN{RS="*, *"}1'
a,b, c
$ echo "a*,b, c" | awk 'BEGIN{RS="*, *"}1'
a
b, c
mawk: GNU awk的手冊規定如下:
12.多行記錄
由於mawk
將RS
解釋為正則表達式 ,因此多行記錄很容易。資料來源:
man mawk
但
11.分割字符串,記錄和文件
Awk程序使用相同的算法通過split()
將字符串拆分為數組,並記錄到FS
字段中。 mawk使用基本上相同的算法將文件拆分為RS
記錄。
Split(expr,A,sep)
工作方式如下:
- <snip>
- 如果
sep = " "
(單個空格),則從expr
的前后修剪<SPACE>,並且sep
變為<SPACE>。 mawk將<SPACE>定義為正則表達式/[ \\t\\n]+/
。 否則,sep
會被視為正則表達式, 只是對於長度為1的字符串會忽略元字符 ,例如split(x, A, "*")
和split(x, A, /\\*/)
相同。- <snip>
資料來源:
man mawk
該手冊未提及應如何解釋以元字符開頭的正則表達式(例如“ * c”)
注意:在GNU awk部分中,我介紹了POSIX awk,因為根據POSIX,形式為"*, "
的正則表達式會導致未定義的行為。 (這與定義RS
無關,因為RS
在POSIX awk中始終不是ERE)
awk實用程序應使用擴展的正則表達式符號(請參閱XBD 擴展的正則表達式 )
來源: Awk Posix標准
和
*+?{
除在方括號表達式中使用時,<asterisk>,<加號>,<question-mark>和<left-brace>應該是特殊的(請參閱RE方括號表達式)。 以下任何一種用途都會產生不確定的結果:
- 如果這些字符首先出現在ERE中 ,或者緊隨未轉義的<vertical-line>,<circumflex>,<dollar-sign>或<left-parenthesis>之后出現
- 如果<left-brace>不是有效間隔表達式的一部分(請參閱匹配多個字符的ERE)
來源: POSIX擴展正則表達式
您能否再嘗試一次。
awk '{gsub(", ","<<<---" ORS)} 1;END{print "<<<---"}' Input_file
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.