【问题标题】:string pattaren-matching using awk使用 awk 进行字符串模式匹配
【发布时间】:2013-10-25 10:26:52
【问题描述】:

(找不到更好的标题)

我正在尝试转换一些行,如下所示:

#define GENERIC_TYPE_METER_PULSE                     0x30 /*Pulse Meter*/
#define SPECIFIC_TYPE_NOT_USED                       0x00 /*Specific Device Class not used*/
......
#define MFG_ID_WAYNE_DALTON                          0x0008   //Wayne Dalton
#define MFG_ID_WILSHINE_HOLDING_CO_LTD               0x012D   //Wilshine Holding Co., Ltd
#define MFG_ID_WIDOM                                 0x0149   //wiDom
......
#define COMMAND_CLASS_ALARM                              0x71
#define COMMAND_CLASS_ALARM_V2                           0x71
#define COMMAND_CLASS_NOTIFICATION_V3                    0x71
#define COMMAND_CLASS_NOTIFICATION_V4                    0x71

在文件 (c++) 中转成类似这样的内容(对于 Java):

SPECIFIC_TYPE_NOT_USED((byte)0x00)             /*Specific Device Class not used*/
MFG_ID_WILSHINE_HOLDING_CO_LTD((byte)0x012D)   //Wilshine Holding Co., Ltd
COMMAND_CLASS_ALARM((byte)0x71)
....

我想出了这个:

gawk '/^#define/ && / [[:xdigit:]]/ { printf "%s((byte)%s)\n",$2,$3 }'

但有两个问题 - 它不适用于 awk;需要 GNU-awk (gawk),而且我还需要输出中的行尾 cmets(只要可用)。我怎样才能做到这一点?我对使用awk 特别感兴趣,但也可以使用sed。干杯!!

【问题讨论】:

  • 哪个部分需要gawk?您可以将十六进制数字与普通字符类匹配0x[0-9a-fA-F]+
  • @Barmar:某些原因0x[0-9a-fA-F]+ 对我不起作用。希望我没有遗漏任何东西。因此尝试gawk 并获得了更好的结果。干杯!!

标签: regex linux bash awk gawk


【解决方案1】:

你可以使用这个 awk 单行:

awk '$1=="#define" && $3~/[0-9]+$/{printf "%s((byte)%s)", $2, $3; $1=$2=$3=""; print}' file

编辑:这是一个 awk,您可以尝试更好地对齐 cmets:

awk '$1 == "#define" && $3 ~ /[0-9]+$/{s=sprintf("%s((byte)%s)", $2, $3); $1=$2=$3="";
     printf("%-50s\t%s\n", s, $0)}'

输出:

GENERIC_TYPE_METER_PULSE((byte)0x30)                      /*Pulse Meter*/
SPECIFIC_TYPE_NOT_USED((byte)0x00)                        /*Specific Device Class not used*/
MFG_ID_WAYNE_DALTON((byte)0x0008)                         //Wayne Dalton
MFG_ID_WIDOM((byte)0x0149)                                //wiDom
COMMAND_CLASS_ALARM((byte)0x71)                           
COMMAND_CLASS_ALARM_V2((byte)0x71)                        
COMMAND_CLASS_NOTIFICATION_V3((byte)0x71)                 
COMMAND_CLASS_NOTIFICATION_V4((byte)0x71)      

【讨论】:

  • 我也在尝试对齐评论栏;当我尝试这样做时,一切都变得一团糟。
  • 嗯,这不是你问题的一部分 :)
  • 是的,我知道;只是贪心!!还有$1=$2=$3="" 是什么意思?
  • 好的,我现在在手机上。将在一个小时内工作以对齐 cmets。
  • 这是一个 awk,您可以尝试更好地对齐 cmets:awk '$1 == "#define" && $3 ~ /[0-9]+$/{s=sprintf("%s((byte)%s)", $2, $3); $1=$2=$3=""; printf("%-50s\t%s\n", s, $0)}'
【解决方案2】:

一个sed的解决方案,我只测试过一次,所以先测试一些案例

[[bash_prompt$]]$ cat log; echo "########";sed -e 's/#define \([^ ]*\)[ ]*\([^ ]*\)/\1((byte)\2)/g' log
#define GENERIC_TYPE_METER_PULSE                     0x30 /*Pulse Meter*/
#define SPECIFIC_TYPE_NOT_USED                       0x00 /*Specific Device Class not used*/
#define MFG_ID_WAYNE_DALTON                          0x0008   //Wayne Dalton
#define MFG_ID_WILSHINE_HOLDING_CO_LTD               0x012D   //Wilshine Holding Co., Ltd
#define MFG_ID_WIDOM                                 0x0149   //wiDom
#define COMMAND_CLASS_ALARM                              0x71
#define COMMAND_CLASS_ALARM_V2                           0x71
#define COMMAND_CLASS_NOTIFICATION_V3                    0x71
#define COMMAND_CLASS_NOTIFICATION_V4                    0x71
########
GENERIC_TYPE_METER_PULSE((byte)0x30) /*Pulse Meter*/
SPECIFIC_TYPE_NOT_USED((byte)0x00) /*Specific Device Class not used*/
MFG_ID_WAYNE_DALTON((byte)0x0008)   //Wayne Dalton
MFG_ID_WILSHINE_HOLDING_CO_LTD((byte)0x012D)   //Wilshine Holding Co., Ltd
MFG_ID_WIDOM((byte)0x0149)   //wiDom
COMMAND_CLASS_ALARM((byte)0x71)
COMMAND_CLASS_ALARM_V2((byte)0x71)
COMMAND_CLASS_NOTIFICATION_V3((byte)0x71)
COMMAND_CLASS_NOTIFICATION_V4((byte)0x71)
[[bash_prompt$]]$

对于正确的格式,(在我的意义上,它正在对齐评论),我无法提出任何 sed 解决方案,(我对其中一个感兴趣)这是一个 awk 解决方案(看起来有点笨拙,但不言自明..

[[bash_prompt$]]$ awk '{str=sprintf("%s((byte)%s)", $2, $3);len=length(str); \
> for(i=50;i>len;i--) str=sprintf("%s ", str); print str (NF>3?substr($0,index($0,$4)):"")}' log
GENERIC_TYPE_METER_PULSE((byte)0x30)              /*Pulse Meter*/
SPECIFIC_TYPE_NOT_USED((byte)0x00)                /*Specific Device Class not used*/
MFG_ID_WAYNE_DALTON((byte)0x0008)                 //Wayne Dalton
MFG_ID_WILSHINE_HOLDING_CO_LTD((byte)0x012D)      //Wilshine Holding Co., Ltd
MFG_ID_WIDOM((byte)0x0149)                        //wiDom
COMMAND_CLASS_ALARM((byte)0x71)
COMMAND_CLASS_ALARM_V2((byte)0x71)
COMMAND_CLASS_NOTIFICATION_V3((byte)0x71)
COMMAND_CLASS_NOTIFICATION_V4((byte)0x71)

【讨论】:

  • 谢谢!我们也可以左对齐评论(输出中的第二个)列吗?干杯!!
  • 查看编辑后的答案,实际上,我的想法是必须有另一种用空格填充字符串的方法,但此时我什么都没有想到,所以你可以继续寻找更好的方法,
  • 这正是我开始使用 awk 的原因。
【解决方案3】:
$ cat tst.awk
/^#/ {
    hd[++nr] = sprintf("%s((byte)%s)", $2, $3)
    lgth = length(hd[nr])
    maxLgth = (lgth > maxLgth ? lgth : maxLgth)

    sub(/[^/]+/,"")
    tl[nr] = $0
}

END {
    for (i=1; i<=nr; i++)
        printf "%-*s%s\n", maxLgth+2, hd[i], tl[i]
}
$ awk -f tst.awk file
GENERIC_TYPE_METER_PULSE((byte)0x30)          /*Pulse Meter*/
SPECIFIC_TYPE_NOT_USED((byte)0x00)            /*Specific Device Class not used*/
MFG_ID_WAYNE_DALTON((byte)0x0008)             //Wayne Dalton
MFG_ID_WILSHINE_HOLDING_CO_LTD((byte)0x012D)  //Wilshine Holding Co., Ltd
MFG_ID_WIDOM((byte)0x0149)                    //wiDom
COMMAND_CLASS_ALARM((byte)0x71)
COMMAND_CLASS_ALARM_V2((byte)0x71)
COMMAND_CLASS_NOTIFICATION_V3((byte)0x71)
COMMAND_CLASS_NOTIFICATION_V4((byte)0x71)

maxLgth+2 中的2 更改为您想要的最长值与其相关注释之间的任何间距。

【讨论】:

    猜你喜欢
    • 2020-10-16
    • 1970-01-01
    • 2013-09-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多