awk: Insert line after comments and imports in source file

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP












0














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='^$' '(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.










share|improve this question























  • (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















0














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='^$' '(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.










share|improve this question























  • (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













0












0








0







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='^$' '(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.










share|improve this question















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='^$' '(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






share|improve this question















share|improve this question













share|improve this question




share|improve this question








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 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
















  • (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















(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










2 Answers
2






active

oldest

votes


















0














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





share|improve this answer




















  • I would hope source code files are not that large!
    – glenn jackman
    Dec 23 '18 at 15:00


















0














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





share|improve this answer






















    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
    );



    );













    draft saved

    draft discarded


















    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









    0














    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





    share|improve this answer




















    • I would hope source code files are not that large!
      – glenn jackman
      Dec 23 '18 at 15:00















    0














    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





    share|improve this answer




















    • I would hope source code files are not that large!
      – glenn jackman
      Dec 23 '18 at 15:00













    0












    0








    0






    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





    share|improve this answer












    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






    share|improve this answer












    share|improve this answer



    share|improve this answer










    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
















    • 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













    0














    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





    share|improve this answer



























      0














      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





      share|improve this answer

























        0












        0








        0






        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





        share|improve this answer














        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






        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Dec 23 '18 at 13:10

























        answered Dec 23 '18 at 9:16









        mosvy

        6,1761425




        6,1761425



























            draft saved

            draft discarded
















































            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.




            draft saved


            draft discarded














            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





















































            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






            Popular posts from this blog

            How to check contact read email or not when send email to Individual?

            Bahrain

            Postfix configuration issue with fips on centos 7; mailgun relay