1

In the UPPER.txt file, I need to substitute APPLE and ORANGE with non-capital apple and orange. I also need to keep the old file UPPER.txt as it was, and a generate a new file lower.txt. I am using the following commands:

sed 's/APPLE/apple/g' UPPER.txt > lower.txt
sed 's/ORANGE/orange/g' UPPER.txt > lower.txt

But the problem is that after I run the above command UPPER.txt and lower.txt become the same containing non-capital items. I want the UPPER.txt to remain as it was originally.

How can I keep a backup of the original file after using sed? Since I want to use this command in C++ using system(command) to operate on the files, I would like all the commands to be written in one line then I can pass it as string to system command.

  • 1
    what you are describing is not the expected behaviour. By default sed does not overwrite the original file; it writes to stdout (hence the result can be redirected using the shell operator > as you showed). Are you showing the exact commands used in your question? – Zanna Apr 21 '18 at 14:58
  • 1
    @SebastianStark if that were so, the redirection would create an empty file, because sed -i doesn't print anything to stdout – Zanna Apr 21 '18 at 15:15
  • 3
    The second command overwrites lowercase.txt and undoes the APPLE change from the first command. You need to chain them. – PerlDuck Apr 21 '18 at 15:34
  • 1
    @Sepideha Please edit to add the text of UPPECASE.txt and lowercase.txt before and after running each sed command. If they're long, you can make a shorter input file and use that. (You needn't call your input file UPPECASE.txt, but either way, please do say explicitly what it is called.) Please also run ls -l UPPECASE.txt lowercase.txt and include the full output in your question. Although it would be strange to have created an alias, function, or alternate external command to make in-place changes when you run sed without -i, please also show the output of type -a sed. – Eliah Kagan Apr 21 '18 at 15:36
  • 2
    @GeorgeUdosen I'm not sure sed is broken here. The recent edit suggests the problem was what PerlDuck said about the second command undoing the effects of the first. I admit that's inconsistent with some of what the question says, but I still think it's the most likely explanation, based on the information available so far. Sepideha: Is that what you meant when you said the input and output files "become the same containing non-capital items"? – Eliah Kagan Apr 21 '18 at 17:16
3

The command you mentioned sed 's/APPLE/apple/g' UPPER.txt > lower.txt shouldn't overwrite the original UPPER.txt, because sed's default behavior is to write to lower.txt. There's something else you've done that may have overwritten the original file. sed doesn't touch the original file unless you provide -i flag. For your purposes, I'd suggest first making a backup of the original file, aka just copy it.

On a side note, please be aware that system() call is kinda evil and shouldn't be used,

  • Thanks for the answer and warning about system(). Which one is more efficient in terms of runtime and memory? 1)first making a backup and running sed- or 2) my solution in EDIT section: running sed and deleting the temp file? – Sepideha Apr 21 '18 at 19:22
  • @Sepideha Your solution uses 3 commands. In shell, I would do sed 's/ORANGE/orrange/g; s/APPLE/apple/g' UPPER.txt > lower.txt. This is just one command, one single process, and redirects shell output to another file. UPPER.txt won't be touched. You of course can do backup as simply as copying the file, that's two commands: cp UPPER.txt UPPER.bak; sed 's/ORANGE/orrange/g; s/APPLE/apple/g' UPPER.txt > lower.txt. But if we're going to avoid system(), then ideal solution would be to capture output from C++ and output to new file (i.e., avoid shell and > operator). – Sergiy Kolodyazhnyy Apr 21 '18 at 19:29
  • @ Sergiy Kolodyazhnyy Thanks for suggesting one-command to do all the job! great help. I am not sure how to avoid system() in this case. You mean first opening UPPER.txt file using c++ ifstream and after processing the text, useing ofstream to write on lower.txt file/buffer? – Sepideha Apr 21 '18 at 19:47
  • @Sepideha Yep, that. You can use popen to avoid system See this example with running a subprocess via popen and capturing output :stackoverflow.com/a/44611186/3701431 – Sergiy Kolodyazhnyy Apr 21 '18 at 21:04
  • 1
    @PerlDuck Yep, that's the smartest route. OP will learn that eventually, one step at a time. – Sergiy Kolodyazhnyy Apr 22 '18 at 8:55
2

I think you have got some misunderstandings.

The sed command only outputs the result in bash. It has nothing to do with original file. The > operator only writes the result to a file.

However, if you want, there is option -i which is able to edit the original file. With -i option comes backup suffix (optional).

$ cat UPPERCASE.txt 
APPLE
$ sed 's/APPLE/apple/g' UPPERCASE.txt
apple
$ sed 's/APPLE/apple/g' UPPERCASE.txt > lowercase.txt
$ cat UPPERCASE.txt 
APPLE
$ cat lowercase.txt 
apple
$ sed 's/APPLE/apple/g' -i[BACKUP] UPPERCASE.txt 
$ cat UPPERCASE.txt 
apple
$ ls
UPPERCASE.txt UPPERCASE.txt[BACKUP] lowercase.txt

Here, the [BACKUP] file is the original file.

  • @Zanna, I understood. Owing to this, In the first and second paragraph I wrote this is misunderstanding. And then I wrote if you want as an alternative. – Olimjon Apr 21 '18 at 15:12

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.