This question already has answers here:
sed in-place flag that works both on Mac (BSD) and Linux
(15 answers)
Closed 4 years ago.
I have got strings stored in two variables (line is current line and new is the replacement). My code looks like this :
sed -i "s#line#new#" output_file
However, this solution does not work on FreeBSD.
Is there any way to modify this code just a bit so it would work?
Yes. Use:
sed -i '' "s#line#new#" output_file
On BSD systems (and macOS too), the sed command's -i option requires a suffix, which may be attached to the -i or a separate argument. However, when the suffix is empty, it must be a separate argument. This is different from GNU sed, where the -i option takes an optional suffix, but if specified, it must be attached to the -i option. Scripts portable between the two (BSD and GNU) therefore must be written with an explicit non-empty suffix attached to the -i option. Note that such scripts may still be unportable to other POSIX systems; the -i option is not standardized (as you can tell from the divergent behaviour).
Related
This is mostly a curiosity question that arose here.
From the man page of GNU sed 4.8 I read
--posix
disable all GNU extensions.
so I understand that if a code like the following works, it means that -i without argument is allowed by POSIX:
sed --posix -i -n '1,25p' *.txt
On the other hand, the same code (with or without --posix) doesn't work for MacOS' BSD sed, because that version expects -i to be followed by an argument.
I can see only two mutually exclusive possibilities:
GNU sed's --posix option allows more than POSIX, which means it bugged and needs a bug report
BSD sed is not POSIX-compliant.
What is the truth?
--posix refers to the sed language itself, not the command line interface:
GNU sed includes several extensions to POSIX sed. In order to simplify writing portable scripts, this option disables all the extensions that this manual documents, including additional commands.
POSIX does not specify -i, so an implementation without it can still be POSIX-conforming.
This question already has answers here:
Write Dollar sign in sed command pattern inside makefile
(2 answers)
Closed 5 years ago.
I have a simple sed replacement for a text file:
sed -i 's/Temp_3/$t0/g' ./somefile.txt
When I use it in a bash script everything works fine.
However, if I try to use the same line from a makefile,
the $t is (probably) expanded into the empty string
(there is no variable called t in the makefile) and
Temp_3 is replaced with 0. What is the best way to solve this?
Thanks!
What happens is that make first does its substitutions,
in your case $t with nothing, then runs the command.
You can, or should ;), circumvent this problem by changing your command as follows: change $ with $$;
make will substitute the double $ sign with a single one.
sed -i 's/Temp_3/$$t0/g' ./somefile.txt
I use torque to submit the test script shown blow
#!/bin/bash
#PBS -N test
#PBS -l nodes=1:ppn=1
#PBS -q ser
#PBS -V
#PBS -S /bin/bash
sed 's/a//' <<< aaabbbaaa
sed 's/\(a\)//' <<< aaabbbaaa
sed 's/a\+//' <<< aaabbbaaa
The expect output should be
aabbbaaa
aabbbaaa
bbbaaa
but actually when i use qsub to submit this file, the output becomes
aabbbaaa
aaabbbaaa
aaabbbaaa
The last two commands do not work. And it seems that the character '\' leads to the fault. But why does this happen.
The sed implementation on the server probably has a different syntax than what you have locally.
Without details about the remote system, this is mildly speculative; but look for the manual page and search for an option to enable Extended Regular Expression syntax (usually -E or -r; if available, probably lose the backslash before the regex specials then).
As a partial and obvious workaround, aa* is equivalent to a\+ but no similar workaround exists for grouping.
Maybe also read up on the differences between POSIX Basic Regular Expression syntax (BRE) and ERE; though chances are your PBS system is using something which even predates POSIX if it's legacy big iron.
If you want to write code which is portable between Linux, MacOS, and whatever behemoth dinosaur OS you have on the PBS system, maybe try Perl instead of sed. Even if you can only rely on Perl 4.x constructs, that's a platform which is a lot more uniform (and also a lot more versatile) than trying to figure out how to write portable sed scripts.
perl -pe 's/(a+)//'
Does anybody know which version of sed is required to get option -i to work? I am on CentOS5 and I am getting this error.
If you're going to be using -i with sed you're doing it wrong. sed is a stream editor and it should be used to edit streams, not files, as -i wants to do.
If you want to edit a file, you should be using ed. ed is a line editor and it should be used to edit files. IMO, that's the tool you want to be using.
btw, -i is a GNUism. from the wikipedia:
GNU sed added several new features. The best-known is in-place editing of files (i.e., replace the original file with the result of applying the sed program), which was later included in BSD sed too. This feature is nowadays often used instead of ed scripts: for example,
I don't think you can get -i to work then.
I think this other SO question may help you out:
sed -i + what the same option in SOLARIS
Perhaps the solution isn't as nice as sed -i, however.
I have the following line in my proftpd log (line 78 to be precise)
Deny from 1.2.3.4
I also have a script which rolls through my logs for people using brute force attacks and then stores their IP (ready for a black listing). What i'm struggling with is inserting (presume with sed) at the end of that specific line - this is what I've got so far:
sed "77i3.4.5.6" /opt/etc/proftpd.conf >> /opt/etc/proftpd.conf
Now one would presume this would work perfectly, however it actually does the following (lines 77 through 78):
3.4.5.6
Deny from 1.2.3.4
I suspect this is due to my dated version of sed, are there any other ways of acheiving the same thing? Also the >> causes the config to be duplicated at the end of the fole (again i'm sure this is a limitation of my version of sed). This is running a homebrew linux kernel on my nas. Sed options below:
root#NAS:~# sed BusyBox v1.7.0
(2009-04-29 19:12:57 JST) multi-call
binary
Usage: sed [-efinr] pattern [files...]
Options:
-e script Add the script to the commands to be executed
-f scriptfile Add script-file contents to the
commands to be executed
-i Edit files in-place
-n Suppress automatic printing of pattern space
-r Use extended regular expression syntax
If no -e or -f is given, the first
non-option argument is taken as the
sed script to interpret. All remaining
arguments are names of input files; if
no input files are specified, then the
standard input is read. Source files
will not be modified unless -i option
is given.
Cheers for your help guys.
This has nothing to do with the version of sed; this is just plain old Doing It Wrong.
sed -i '77s/$/,3.4.5.6/' /opt/etc/proftpd.conf