Find and replace in file and overwrite file doesn't work, it empties the file

后端 未结 13 2097
深忆病人
深忆病人 2020-11-22 08:45

I would like to run a find and replace on an HTML file through the command line.

My command looks something like this:

sed -e s/STRING_TO_REPLACE/STR         


        
相关标签:
13条回答
  • 2020-11-22 09:25

    When the shell sees > index.html in the command line it opens the file index.html for writing, wiping off all its previous contents.

    To fix this you need to pass the -i option to sed to make the changes inline and create a backup of the original file before it does the changes in-place:

    sed -i.bak s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g index.html
    

    Without the .bak the command will fail on some platforms, such as Mac OSX.

    0 讨论(0)
  • 2020-11-22 09:25

    An alternative, useful, pattern is:

    sed -e 'script script' index.html > index.html.tmp && mv index.html.tmp index.html
    

    That has much the same effect, without using the -i option, and additionally means that, if the sed script fails for some reason, the input file isn't clobbered. Further, if the edit is successful, there's no backup file left lying around. This sort of idiom can be useful in Makefiles.

    Quite a lot of seds have the -i option, but not all of them; the posix sed is one which doesn't. If you're aiming for portability, therefore, it's best avoided.

    0 讨论(0)
  • 2020-11-22 09:25

    The problem with the command

    sed 'code' file > file
    

    is that file is truncated by the shell before sed actually gets to process it. As a result, you get an empty file.

    The sed way to do this is to use -i to edit in place, as other answers suggested. However, this is not always what you want. -i will create a temporary file that will then be used to replace the original file. This is problematic if your original file was a link (the link will be replaced by a regular file). If you need to preserve links, you can use a temporary variable to store the output of sed before writing it back to the file, like this:

    tmp=$(sed 'code' file); echo -n "$tmp" > file
    

    Better yet, use printf instead of echo since echo is likely to process \\ as \ in some shells (e.g. dash):

    tmp=$(sed 'code' file); printf "%s" "$tmp" > file
    
    0 讨论(0)
  • 2020-11-22 09:27

    use sed's -i option, e.g.

    sed -i bak -e s/STRING_TO_REPLACE/REPLACE_WITH/g index.html
    
    0 讨论(0)
  • 2020-11-22 09:27

    And the ed answer:

    printf "%s\n" '1,$s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g' w q | ed index.html
    

    To reiterate what codaddict answered, the shell handles the redirection first, wiping out the "input.html" file, and then the shell invokes the "sed" command passing it a now empty file.

    0 讨论(0)
  • 2020-11-22 09:27

    With all due respect to the above correct answers, it's always a good idea to "dry run" scripts like that, so that you don't corrupt your file and have to start again from scratch.

    Just get your script to spill the output to the command line instead of writing it to the file, for example, like that:

    sed -e s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g index.html
    

    OR

    less index.html | sed -e s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g 
    

    This way you can see and check the output of the command without getting your file truncated.

    0 讨论(0)
提交回复
热议问题