awk:在源文件中的注释和导入后插入行

awk:在源文件中的注释和导入后插入行

我有一堆具有非常常见结构的源文件:标头中的一些注释,一些(可选)导入,然后是源代码,例如:

//
//  AppDelegate.swift
//  settings
//
//  Created by Mikhail Igonin on 14/06/2018.
//  Copyright © 2018 Mikhail Igonin. All rights reserved.
// 


import UIKit
import Fabric
import Crashlytics


@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
    //Other comment
}

我需要在注释和导入块之后添加另一个导入。因此匹配该文件开头的正则表达式应如下所示:

(([\n\s]*)((\/\/.*\n)|(import.*\n)))+

看起来这个正则表达式没问题:https://www.regextester.com/index.php?fam=106706

现在我尝试用awkand插入新的导入gensub

gawk -v RS='^$' '{$0=gensub(/(([\n\s]*)((\/\/.*\n)|(import.*\n)))+/,"\\1\\2\nimport NEW_IMPORT\n\\2",1)}1' test.swift

但是它不起作用,我的正则表达式匹配所有文件:

//
//  AppDelegate.swift
//  settings
//
//  Created by Mikhail Igonin on 14/06/2018.
//  Copyright © 2018 Mikhail Igonin. All rights reserved.
//


import UIKit
import Fabric
import Crashlytics


@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

}

import NEW_IMPORT

我有什么错?看起来.*工作不正确并且匹配所有文件。我尝试将其标记为惰性 ( .*?) 但也没有成功。

没有 awk 或 gensub 的 PS 解决方案也很有用。

答案1

对于大文件可能不是最有效的,但会在import ...找到的 LAST 语句之后插入新的导入行:

tac file | awk '/^import/ && !I {I = 1; print "import New_IMPORT"} 1' | tac

答案2

您的错误是假设.(如.*) 与 : 中的换行符不匹配awk。这与sedgrepperl、等不同。javascript(将正则表达式视为awk总是贪婪的并且//s标志始终打开)。

设置RS^$将导致awk将整个文件作为单个记录,然后模式将从文件中的\/\/.*\n第一个到最后一个换行符进行匹配;甚至不会考虑分支//import.*\n

可能有更聪明的方法来做到这一点,但这会在文件中的import NEW_IMPORT第一行行之后插入该行:import

awk '!e&&/^import/,e=!/^import/{if(e)print "import NEW_IMPORT"}1' test.swift

相关内容