我有一堆具有非常常见结构的源文件:标头中的一些注释,一些(可选)导入,然后是源代码,例如:
//
// 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
现在我尝试用awk
and插入新的导入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
。这与sed
、grep
、perl
、等不同。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