0

I've been looking for a way to find-and-replace strings in all fortran files in my current directory. Most answers on here are along the lines of using:

sed -i 's/INCLUDE \'atm/params.inc\'/USE params/g' *.f

or

perl -pi -w -e 's/INCLUDE \'atm/params.inc\'/USE params/g' *.f

However, when I use either of these the bash line continuation > pops up on the next line as if it's expecting input or another argument. I haven't seen anyone else encounter this and I am not sure what to do with it. Are my commands incorrect; am I missing something?

12
  • BashFAQ #21, at mywiki.wooledge.org/BashFAQ/021, gives the canonical mechanism for doing this. Commented Jun 14, 2016 at 15:10
  • 1
    BTW, sed -i is a non-standard extension -- the POSIX standard for sed doesn't guarantee that it'll be available, and even when it is available it may behave in different ways (the MacOS X version won't work with your given command). If you want to write portable code, consider using ex instead, or another mechanism given as standards-compliant in the above-mentioned FAQ. Commented Jun 14, 2016 at 15:12
  • Can you confirm that you can reproduce the bug with the exact commands given here? Specifically, 's/old-string/new-string/g', with old-string and new-string as the literal, exact source and destination text (not some other text for which you're using those strings as placeholders)? Commented Jun 14, 2016 at 15:18
  • BTW, large parts of this are not really bash-related -- sed is not part of the shell, but provided by the operating system (meaning we don't know how sed -i is supposed to behave unless we know the OS you're running, and knowing that your shell is bash vs ash or whatever has no bearing on that behavior once sed is invoked). However, I'm theorizing that the actual source and destination strings you're using parse in a manner you don't expect by the shell, with the effect that sed isn't actually being started -- but we can't diagnose that without those actual strings. Commented Jun 14, 2016 at 15:22
  • ...and, yeah, there's your problem. \' isn't how you substitute a single-quote in a single-quoted string. Commented Jun 14, 2016 at 15:25

1 Answer 1

4

There are two problems with the original:

  • You weren't protecting your / in the literal data from being parsed by sed rather than treated as data. One very readable and explicit way to do this is with [/].
  • You were trying to use \' to put a literal ' in a single-quoted string. That doesn't work. The common idiom is '"'"', which, character-by-character, does the following:

    1. ' - exits the original single-quoted context
    2. " - opens a double-quoted context
    3. ' - adds a literal single-quote (protected by the surrounding double quotes)
    4. " - ends that double-quoted context
    5. ' - resumes the outer single-quoted context.

Thus, consider:

# note: this works with GNU sed, not MacOS sed or others
sed -i 's/INCLUDE '"'"'atm[/]params.inc'"'"'/USE params/g' *.f
Sign up to request clarification or add additional context in comments.

4 Comments

Thanks, that was a mistype of the question which I just edited. I have not been typing the actual commands this way. I am not sure what other code you'd like to see since I am not doing anything other than this one command.
@WhS4, do you get the given behavior with the exact strings old-string and new-string? If not, you'll need to build a better example.
Thanks! This worked perfectly. I suppose I should have read up on my syntax a bit more before diving in, but thank you none the less.
just a side note: I found another solution to the literal / problem. sed can use any character as a delimiter, so when dealing with strings containing /, some people use @ (although anything not in the strings would work) for the delimiter. I tested and this works

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.