awk: Insert line after comments and imports in source file
I have bunch of source files with very usual structure: some comments in header, some (optional) imports, and then source code, e.g.:
//
// 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
}
I need to add another import after comments and import block. So regex to match beginning of this file should look like this:
(([ns]*)((//.*n)|(import.*n)))+
And looks like this regex is ok: https://www.regextester.com/index.php?fam=106706
Now I'm trying to inset new import with awk
and gensub
:
gawk -v RS='^$' '{$0=gensub(/(([ns]*)((//.*n)|(import.*n)))+/,"\1\2nimport NEW_IMPORTn\2",1)}1' test.swift
However it doesn't work and my regex match all file:
//
// 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
What's my mistake? Looks like .*
works incorrect and match all file. I've tried to mark it as lazy (.*?
) but without success also.
PS Solutions without awk or gensub would be also useful.
awk regular-expression
add a comment |
I have bunch of source files with very usual structure: some comments in header, some (optional) imports, and then source code, e.g.:
//
// 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
}
I need to add another import after comments and import block. So regex to match beginning of this file should look like this:
(([ns]*)((//.*n)|(import.*n)))+
And looks like this regex is ok: https://www.regextester.com/index.php?fam=106706
Now I'm trying to inset new import with awk
and gensub
:
gawk -v RS='^$' '{$0=gensub(/(([ns]*)((//.*n)|(import.*n)))+/,"\1\2nimport NEW_IMPORTn\2",1)}1' test.swift
However it doesn't work and my regex match all file:
//
// 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
What's my mistake? Looks like .*
works incorrect and match all file. I've tried to mark it as lazy (.*?
) but without success also.
PS Solutions without awk or gensub would be also useful.
awk regular-expression
(1) Have you tried printing the records (i.e.,$0
values) that you're getting?RS='^$'
might get you each stanza (block of non-blank lines) as a record, so the comments will be the first record, the imports will be the second record, and you'll never see both at the same time. (2) You might be better off usingawk
as a state machine rather than trying to do a multi-line regex.
– G-Man
Dec 23 '18 at 7:59
The tester is set tojavascript
, btw, not sure that's what awk uses ... switching it to PCRE doesn't give a match ...
– tink
Dec 23 '18 at 8:28
add a comment |
I have bunch of source files with very usual structure: some comments in header, some (optional) imports, and then source code, e.g.:
//
// 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
}
I need to add another import after comments and import block. So regex to match beginning of this file should look like this:
(([ns]*)((//.*n)|(import.*n)))+
And looks like this regex is ok: https://www.regextester.com/index.php?fam=106706
Now I'm trying to inset new import with awk
and gensub
:
gawk -v RS='^$' '{$0=gensub(/(([ns]*)((//.*n)|(import.*n)))+/,"\1\2nimport NEW_IMPORTn\2",1)}1' test.swift
However it doesn't work and my regex match all file:
//
// 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
What's my mistake? Looks like .*
works incorrect and match all file. I've tried to mark it as lazy (.*?
) but without success also.
PS Solutions without awk or gensub would be also useful.
awk regular-expression
I have bunch of source files with very usual structure: some comments in header, some (optional) imports, and then source code, e.g.:
//
// 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
}
I need to add another import after comments and import block. So regex to match beginning of this file should look like this:
(([ns]*)((//.*n)|(import.*n)))+
And looks like this regex is ok: https://www.regextester.com/index.php?fam=106706
Now I'm trying to inset new import with awk
and gensub
:
gawk -v RS='^$' '{$0=gensub(/(([ns]*)((//.*n)|(import.*n)))+/,"\1\2nimport NEW_IMPORTn\2",1)}1' test.swift
However it doesn't work and my regex match all file:
//
// 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
What's my mistake? Looks like .*
works incorrect and match all file. I've tried to mark it as lazy (.*?
) but without success also.
PS Solutions without awk or gensub would be also useful.
awk regular-expression
awk regular-expression
edited Dec 23 '18 at 9:35
Rui F Ribeiro
39.2k1479130
39.2k1479130
asked Dec 23 '18 at 7:48
frozen_lion
101
101
(1) Have you tried printing the records (i.e.,$0
values) that you're getting?RS='^$'
might get you each stanza (block of non-blank lines) as a record, so the comments will be the first record, the imports will be the second record, and you'll never see both at the same time. (2) You might be better off usingawk
as a state machine rather than trying to do a multi-line regex.
– G-Man
Dec 23 '18 at 7:59
The tester is set tojavascript
, btw, not sure that's what awk uses ... switching it to PCRE doesn't give a match ...
– tink
Dec 23 '18 at 8:28
add a comment |
(1) Have you tried printing the records (i.e.,$0
values) that you're getting?RS='^$'
might get you each stanza (block of non-blank lines) as a record, so the comments will be the first record, the imports will be the second record, and you'll never see both at the same time. (2) You might be better off usingawk
as a state machine rather than trying to do a multi-line regex.
– G-Man
Dec 23 '18 at 7:59
The tester is set tojavascript
, btw, not sure that's what awk uses ... switching it to PCRE doesn't give a match ...
– tink
Dec 23 '18 at 8:28
(1) Have you tried printing the records (i.e.,
$0
values) that you're getting? RS='^$'
might get you each stanza (block of non-blank lines) as a record, so the comments will be the first record, the imports will be the second record, and you'll never see both at the same time. (2) You might be better off using awk
as a state machine rather than trying to do a multi-line regex.– G-Man
Dec 23 '18 at 7:59
(1) Have you tried printing the records (i.e.,
$0
values) that you're getting? RS='^$'
might get you each stanza (block of non-blank lines) as a record, so the comments will be the first record, the imports will be the second record, and you'll never see both at the same time. (2) You might be better off using awk
as a state machine rather than trying to do a multi-line regex.– G-Man
Dec 23 '18 at 7:59
The tester is set to
javascript
, btw, not sure that's what awk uses ... switching it to PCRE doesn't give a match ...– tink
Dec 23 '18 at 8:28
The tester is set to
javascript
, btw, not sure that's what awk uses ... switching it to PCRE doesn't give a match ...– tink
Dec 23 '18 at 8:28
add a comment |
2 Answers
2
active
oldest
votes
May not be the most efficient for large files, but inserts the new import line after the LAST import ...
statement found:
tac file | awk '/^import/ && !I {I = 1; print "import New_IMPORT"} 1' | tac
I would hope source code files are not that large!
– glenn jackman
Dec 23 '18 at 15:00
add a comment |
Your mistake is to assume that .
(as in .*
) doesn't match a newline in awk
: it does. That's different from sed
, grep
, perl
, javascript
, etc. (Think of awk
regexps as always greedy and with the //s
flag always on).
Setting RS
to ^$
will cause awk
to slurp the whole file as a single record, and then the //.*n
pattern will match from the first //
up to the last newline in the file; the import.*n
branch won't even be considered.
There are probably smarter ways to do it, but this will insert the import NEW_IMPORT
line after the first run of import
lines from your file:
awk '!e&&/^import/,e=!/^import/{if(e)print "import NEW_IMPORT"}1' test.swift
add a comment |
Your Answer
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "106"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f490564%2fawk-insert-line-after-comments-and-imports-in-source-file%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
May not be the most efficient for large files, but inserts the new import line after the LAST import ...
statement found:
tac file | awk '/^import/ && !I {I = 1; print "import New_IMPORT"} 1' | tac
I would hope source code files are not that large!
– glenn jackman
Dec 23 '18 at 15:00
add a comment |
May not be the most efficient for large files, but inserts the new import line after the LAST import ...
statement found:
tac file | awk '/^import/ && !I {I = 1; print "import New_IMPORT"} 1' | tac
I would hope source code files are not that large!
– glenn jackman
Dec 23 '18 at 15:00
add a comment |
May not be the most efficient for large files, but inserts the new import line after the LAST import ...
statement found:
tac file | awk '/^import/ && !I {I = 1; print "import New_IMPORT"} 1' | tac
May not be the most efficient for large files, but inserts the new import line after the LAST import ...
statement found:
tac file | awk '/^import/ && !I {I = 1; print "import New_IMPORT"} 1' | tac
answered Dec 23 '18 at 10:51
RudiC
4,2041312
4,2041312
I would hope source code files are not that large!
– glenn jackman
Dec 23 '18 at 15:00
add a comment |
I would hope source code files are not that large!
– glenn jackman
Dec 23 '18 at 15:00
I would hope source code files are not that large!
– glenn jackman
Dec 23 '18 at 15:00
I would hope source code files are not that large!
– glenn jackman
Dec 23 '18 at 15:00
add a comment |
Your mistake is to assume that .
(as in .*
) doesn't match a newline in awk
: it does. That's different from sed
, grep
, perl
, javascript
, etc. (Think of awk
regexps as always greedy and with the //s
flag always on).
Setting RS
to ^$
will cause awk
to slurp the whole file as a single record, and then the //.*n
pattern will match from the first //
up to the last newline in the file; the import.*n
branch won't even be considered.
There are probably smarter ways to do it, but this will insert the import NEW_IMPORT
line after the first run of import
lines from your file:
awk '!e&&/^import/,e=!/^import/{if(e)print "import NEW_IMPORT"}1' test.swift
add a comment |
Your mistake is to assume that .
(as in .*
) doesn't match a newline in awk
: it does. That's different from sed
, grep
, perl
, javascript
, etc. (Think of awk
regexps as always greedy and with the //s
flag always on).
Setting RS
to ^$
will cause awk
to slurp the whole file as a single record, and then the //.*n
pattern will match from the first //
up to the last newline in the file; the import.*n
branch won't even be considered.
There are probably smarter ways to do it, but this will insert the import NEW_IMPORT
line after the first run of import
lines from your file:
awk '!e&&/^import/,e=!/^import/{if(e)print "import NEW_IMPORT"}1' test.swift
add a comment |
Your mistake is to assume that .
(as in .*
) doesn't match a newline in awk
: it does. That's different from sed
, grep
, perl
, javascript
, etc. (Think of awk
regexps as always greedy and with the //s
flag always on).
Setting RS
to ^$
will cause awk
to slurp the whole file as a single record, and then the //.*n
pattern will match from the first //
up to the last newline in the file; the import.*n
branch won't even be considered.
There are probably smarter ways to do it, but this will insert the import NEW_IMPORT
line after the first run of import
lines from your file:
awk '!e&&/^import/,e=!/^import/{if(e)print "import NEW_IMPORT"}1' test.swift
Your mistake is to assume that .
(as in .*
) doesn't match a newline in awk
: it does. That's different from sed
, grep
, perl
, javascript
, etc. (Think of awk
regexps as always greedy and with the //s
flag always on).
Setting RS
to ^$
will cause awk
to slurp the whole file as a single record, and then the //.*n
pattern will match from the first //
up to the last newline in the file; the import.*n
branch won't even be considered.
There are probably smarter ways to do it, but this will insert the import NEW_IMPORT
line after the first run of import
lines from your file:
awk '!e&&/^import/,e=!/^import/{if(e)print "import NEW_IMPORT"}1' test.swift
edited Dec 23 '18 at 13:10
answered Dec 23 '18 at 9:16
mosvy
6,1761425
6,1761425
add a comment |
add a comment |
Thanks for contributing an answer to Unix & Linux Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f490564%2fawk-insert-line-after-comments-and-imports-in-source-file%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
(1) Have you tried printing the records (i.e.,
$0
values) that you're getting?RS='^$'
might get you each stanza (block of non-blank lines) as a record, so the comments will be the first record, the imports will be the second record, and you'll never see both at the same time. (2) You might be better off usingawk
as a state machine rather than trying to do a multi-line regex.– G-Man
Dec 23 '18 at 7:59
The tester is set to
javascript
, btw, not sure that's what awk uses ... switching it to PCRE doesn't give a match ...– tink
Dec 23 '18 at 8:28