Redirect output from sed 's/c/d/' myFile to myFile

后端 未结 10 829
暖寄归人
暖寄归人 2020-12-09 10:15

I am using sed in a script to do a replace and I want to have the replaced file overwrite the file. Normally I think that you would use this:

% sed -i \'s/c         


        
相关标签:
10条回答
  • 2020-12-09 10:40

    A lot of answers, but none of them is correct. Here is the correct and simplest one:

    $ echo "111 222 333" > file.txt
    $ sed -i -s s/222/444/ file.txt 
    $ cat file.txt
    111 444 333
    $ 
    
    0 讨论(0)
  • 2020-12-09 10:46

    I commonly use the 3rd way, but with an important change:

    $ sed 's/cat/dog/' manipulate > tmp && mv tmp manipulate

    I.e. change ; to && so the move only happens if sed is successful; otherwise you'll lose your original file as soon as you make a typo in your sed syntax.

    Note! For those reading the title and missing the OP's constraint "my sed doesn't support -i": For most people, sed will support -i, so the best way to do this is:

    $ sed -i 's/cat/dog/' manipulate

    0 讨论(0)
  • 2020-12-09 10:46

    Workaround using open file handles:

    exec 3<manipulate 
    

    Prevent open file from being truncated:

    rm manipulate
    sed 's/cat/dog/' <&3 > manipulate
    
    0 讨论(0)
  • 2020-12-09 10:51

    Kernighan and Pike in The Art of Unix Programming discuss this issue. Their solution is to write a script called overwrite, which allows one to do such things.

    The usage is: overwrite file cmd file.

    # overwrite: copy standard input to output after EOF
    
    opath=$PATH
    PATH=/bin:/usr/bin
    
    case $# in
    0|1)   echo 'Usage: overwrite file cmd [args]' 1>&2; exit 2
    esac
    
    file=$1; shift
    new=/tmp/overwr1.$$; old=/tmp/overwr2.$$
    trap 'rm -f $new $old; exit 1' 1 2 15  # clean up
    
    if PATH=$opath "$@" >$new
    then
           cp $file $old           # save original
           trap '' 1 2 15          # wr are commmitted
           cp $new $file
    else
           echo "overwrite: $1 failed, $file unchanged" 1>&2
           exit 1
    fi
    rm -f $new $old
    

    Once you have the above script in your $PATH, you can do:

    overwrite manipulate sed 's/cat/dog/' manipulate
    

    To make your life easier, you can use replace script from the same book:

    # replace: replace  str1 in files with str2 in place
    PATH=/bin:/usr/bin
    
    case $# in
        0|2) echo 'Usage: replace str1 str2 files' 1>&2; exit 1
    esac
    
    left="$1"; right="$2"; shift; shift
    
    for i
    do
        overwrite $i sed "s@$left@$right@g" $i
    done
    

    Having replace in your $PATH too will allow you to say:

    replace cat dog manipulate
    
    0 讨论(0)
  • 2020-12-09 10:55

    Perhaps -i is gnu sed, or just an old version of sed, but anyways. You're on the right track. The first option is probably the most common one, the third option is if you want it to work everywhere (including solaris machines)... :) These are the 'standard' ways of doing it.

    0 讨论(0)
  • 2020-12-09 10:56

    Yes, -i is also supported in FreeBSD/MacOSX sed, but needs the empty string as an argument to edit a file in-place.

    sed -i "" 's/old/new/g' file   # FreeBSD sed
    
    0 讨论(0)
提交回复
热议问题