RS以AWK语言

时间:2018-12-04 16:26:51

标签: bash awk mawk

我正在学习awk编程语言,并且在这里遇到了问题。

我有一个文件(awk.dat),内容如下:

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. <<<--- 之间的空格的含义,因为它会引发错误。

预期输出:

public static void Main(string[] args)
    {
        string TrackingNumber1;
        string TrackingNumber2;
        string TrackingNumber3;

        Console.WriteLine("Enter First Tracking Number:");
        TrackingNumber1 = Console.ReadLine();

        Console.WriteLine("Enter Second Tracking Number:");
        TrackingNumber2 = Console.ReadLine();

        Console.WriteLine("Enter Third Tracking Number:");
        TrackingNumber3 = Console.ReadLine();
    }
    public class UspsService
    {

        //Base URL for USPS Address and Zip Code validation API
        private const string baseURL = "http://testurl.com";
        //Web client instance.
        private WebClient wsClient = new WebClient();
        //User ID obtained from USPS.
        public string usps_UserID = "";

        private string GetDataFromSite(string uspsRequest)
        {
            string strResponse = "";
            //Send the request to USPS.
            byte[] responseData = wsClient.DownloadData(uspsRequest);
            //Convert byte stream to string data.
            foreach (byte oItem in responseData)
                strResponse += (char)oItem;
            return strResponse;
        }


        //method that builds the track request, and sends returns the formatted string to send to USPS endpoint
        public string TrackRequest(string trackingNumber1, string trackingNumber2, string trackingNumber3)
        {
            string strResponse = "", strUSPS = "";
            strUSPS = baseURL + "?API=TrackV2&XML=<?xml version =\"1.0\" encoding =\"utf-8\"?>";
            strUSPS += "<TrackRequest USERID=\"" + usps_UserID + "\">";
            strUSPS += "<TrackID ID=\"" + trackingNumber1 + "\"> </TrackID>";
            strUSPS += "<TrackID ID=\"" + trackingNumber2 + "\"> </TrackID>";
            strUSPS += "<TrackID ID=\"" + trackingNumber3 + "\"> </TrackID>";
            strUSPS += "</TrackRequest>";
            //Send the request to USPS.
            strResponse = GetDataFromSite(strUSPS);
            Console.WriteLine(strResponse);
            return strResponse;

        }

谢谢。

3 个答案:

答案 0 :(得分:3)

"[space1]*,[space2]*"

是正则表达式,它与以下字符串匹配:

零个或多个空格(space1)后跟一个逗号,然后是零个或多个空格(space2)

第一个"*,[space]*"是错误的,因为*在正则表达式中具有特殊含义。这意味着将匹配的组/字符重复零次或多次。您不能一开始就将其放置。

答案 1 :(得分:1)

请注意,根据POSIX,RS被定义为单个字符,而不是正则表达式。

  

RS字符串值的第一个字符应为输入记录分隔符;默认情况下为。如果RS包含多个字符,则结果不确定。如果RS为空,则记录由由加上一个或多个空行组成的序列分隔,开头或结尾的空行在输入的开头或结尾不应导致空记录,并且不管FS的值是什么,都应该始终是字段分隔符。

     

来源:Awk Posix standard

这意味着RS=" *, *"导致不确定的行为

实现POSIX扩展的其他版本的awk,可能对RS的含义采用不同的方法。例如GNU awk和mawk。两者都将RS实现为正则表达式,但是两种实现都略有不同。 用法的摘要如下:

| RS   | awk (posix)  | gawk             | mawk             |
|------+--------------+------------------+------------------|
| "*"  | "<asterisk>" | "<asterisk>"     | "<asterisk>"     |
| "*c" | undefined    | "<asterisk>c"    | undefined        |
| "c*" | undefined    | "","c","ccc",... | "","c","ccc",... |

c is any character

根据mawk,以上RS="*, *"是无效的正则表达式,因此应该解释OP的错误。

$ echo "abc" | ./mawk '/*c/'
mawk: line 1: regular expression compile failed (missing operand)

GNU awk: GNU awk手册规定以下内容:

  

使用gawk时, RS的值不限于一个字符的字符串。它可以是任何正则表达式(请参见Regexp)。 (c.e.)通常,每个记录都在与正则表达式匹配的下一个字符串处结束;下一条记录从匹配字符串的末尾开始。

     

来源:GNU awk manual

要了解在GNU awk的正则表达式中的用法,我们发现:

  

<星号> * 这个符号表示前面的正则表达式应该重复多次以找到匹配项。例如,ph**符号应用于前面的h,并寻找一个p的匹配项,后跟任意数量的h。如果不存在p,则这也仅与h相匹配。

     

要了解*的工作原理,有两点要注意。首先,*仅适用于单个前面的正则表达式组件(例如,在ph*中,它仅适用于h)。要使*适用于较大的子表达式,请使用括号:(ph)*匹配phphphphphph等。

     

第二,*找到尽可能多的重复。如果要匹配的文本是phhhhhhhhhhhhhhooey,则ph*匹配所有h

     

来源:GNU Regular expression operators

但是必须指出的是:

  

POSIX awk 和gawk中,当在正则表达式中没有任何正则表达式时, *+?运算符就代表自己。例如,/+/与文字加号匹配。但是,许多其他版本的awk会将这种用法视为语法错误。

     

来源:GNU Regular expression operators

因此,设置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)的工作方式如下:

     
      
  1.   
  2. 如果sep = " "(单个空格),则从expr的正面和背面修剪,并且sep变为。 mawk将定义为正则表达式/[ \t\n]+/。否则,sep被视为正则表达式,除外,元字符除外   对于长度为1的字符串会被忽略,例如split(x, A, "*")split(x, A, /\*/)相同。
  3.   
  4.   
     

来源:man mawk

手册没有提及应如何解释以元字符开头的正则表达式(例如“ * c”)


注意:在POSIX awk中,我触及了GNU awk部分,因为根据POSIX,形式为"*, "的正则表达式会导致未定义的行为。 (这与将RS定义为RS始终不是POSIX awk中的ERE无关)

  

awk实用程序应使用扩展的正则表达式符号(请参见XBD Extended Regular Expressions

     

来源:Awk Posix standard

  

*+?{   除在方括号表达式中使用时,,<加号>,应该是特殊的(请参见RE方括号表达式)。 以下任何用途都会产生不确定的结果:

     
      
  • 如果这些字符首先出现在ERE中,或者紧随未转义的
  •   
  • 如果不是有效间隔表达式的一部分(请参阅匹配多个字符的ERE)
  •   
     

来源:POSIX Extended Regular Expressions

答案 2 :(得分:1)

请您尝试一次。

awk '{gsub(", ","<<<---" ORS)} 1;END{print "<<<---"}'   Input_file