Sed - 复制函数参数和注释

时间:2017-09-21 06:30:25

标签: sed

C文件有100个带strlcpy的行,我必须复制第一个参数并添加为strlpcy的第三个参数 - 例如p->account to sizeof(p->account)

输入

strlcpy(p->account,gettoken(NULL,&plast));      //Set Account Information
strlcpy(p->balance,gettoken(NULL,&plast));
strlcpy(p->startDate,skipchr(gettoken(NULL,&plast),'0')); /* YYYYMMDD */
strlcpy(p->endDate,skipchr(gettoken(NULL,&plast),'0')); /* YYYYMMDD */
strlcpy(p->status,gettoken(NULL,&plast));

预期输出(复制第一个参数并添加为第三个参数 - 作为sizeof()的参数传递);

strlcpy(p->account,gettoken(NULL,&plast),sizeof(p->account));     //Set Account Information
strlcpy(p->balance,gettoken(NULL,&plast),sizeof(p->balance));
strlcpy(p->startDate,skipchr(gettoken(NULL,&plast),'0'),sizeof(p->startDate)); /* YYYYMMDD */
strlcpy(p->endDate,skipchr(gettoken(NULL,&plast),'0'),sizeof(p->endDate)); /* YYYYMMDD */
strlcpy(p->status,gettoken(NULL,&plast),sizeof(p->status));

当前输出(不正确的结果)

sed 's/^\([^\s]*strlcpy[^(]*\)\(([^,]*\),\([^)]*[^)][^;]\).*/\1\2,\3,sizeof\2));/' kkk1.txt

strlcpy(p->account,gettoken(NULL,&plast),sizeof(p->account));
strlcpy(p->balance,gettoken(NULL,&plast),sizeof(p->balance));
strlcpy(p->startDate,skipchr(gettoken(NULL,&plast),sizeof(p->startDate));
strlcpy(p->endDate,skipchr(gettoken(NULL,&plast),sizeof(p->endDate));
strlcpy(p->status,gettoken(NULL,&plast),sizeof(p->status));

第1,3和4行无法在行尾

打印注释

第3行和第4行:skipchr(gettoken(NULL,&plast),'0') - 参数'0'未能在结果中与resultch中的skipchr()一起复制。

使用正确的sed命令指导我。感谢Advnace

3 个答案:

答案 0 :(得分:1)

一般,这样的任务超出了sed的威力。那是因为C有一个(大约)无上下文语法,只能用常规表达式解析。例如,常规语法不能描述任意嵌套的括号。

但是,如果您对输入有足够的限制,则可以将sed用于特定的受约束源代码。在这种情况下,似乎我们可以做出这些假设:

  • 每条相关陈述都在一行
  • 每条相关行只有一条陈述。
  • 第一个参数不包含逗号。
  • 没有可能意外匹配的字符串文字或注释。

鉴于这些限制,我们希望匹配:

  1. strlcpy名称和左括号(可选空格):\bstrlcpy\s*(
  2. 第一个参数,直到第一个逗号:[^,]+
  3. 其余论点:,.+
  4. 最后的右括号和分号:)\s*;
  5. 我们希望用相同的文字替换它,除了我们希望sizeof组2插入替换组{3}中的组3和组4之间。

    将它们组合成GNU sed one-liner:

    \1\2\3, sizeof \2\4

    通过这个提供示例代码可以得到所需的输出:

    #!/bin/sed -rf
    
    s/\b(strlcpy\s*\()([^,]+)(,.+)(\)\s*;)/\1\2\3, sizeof \2\4/
    

    (注意:我没有在strlcpy(p->account,gettoken(NULL,&plast), sizeof p->account); //Set Account Information strlcpy(p->balance,gettoken(NULL,&plast), sizeof p->balance); strlcpy(p->startDate,skipchr(gettoken(NULL,&plast),'0'), sizeof p->startDate); /* YYYYMMDD */ strlcpy(p->endDate,skipchr(gettoken(NULL,&plast),'0'), sizeof p->endDate); /* YYYYMMDD */ strlcpy(p->status,gettoken(NULL,&plast), sizeof p->status); 的参数周围添加不​​必要的括号,因为这使得它看起来像将sizeof应用于类型而不是表达式;如果你感觉非常强烈你想要它们,这并不困难。但我不鼓励它。)

答案 1 :(得分:0)

$ str="strlcpy(p->account,gettoken(NULL,&plast));"
$ sed -re '/strlcpy/{s/(\([^,]*)([^\)]*\))/\1\2,sizeof\1\)/}' <<< "$str"
strlcpy(p->account,gettoken(NULL,&plast),sizeof(p->account));

以下是简要说明,

  • /strlcpy/:找到匹配的行&#34; strcpy&#34;,并使用后面的脚本来处理它
  • (...)\1\2引用括号(...)之间相应的匹配正则表达式。请注意,由于-r参数,无需转义括号。
  • 包含括号的正则表达式模式,需要转义为\(
  • 编辑文件的最后一步,添加-i选项来执行此操作。

答案 2 :(得分:-2)

试试这个:

SELECT * 
FROM attendance_days
  LEFT OUTER JOIN employee_attendance 
               ON employee_attendance.attendance_day_id = attendance_days.id