2

I want do delete, say line number three of the file a. How can I do this with tools like sed or awk in a way that it's compatible with the POSIX specification? I know I could do sed -i '3d' a, but the -i flag is not specified by POSIX for sed.

Of course I could run the same sed command without the -i flag, save to a temporary file and then replace the original file with the new one; but I would prefer a one-liner.

Luis Lavaire.
  • 599
  • 5
  • 17

4 Answers4

2

Following may help here.

awk -v line=3 'FNR==line{next} 1' Input_file

Explanation:

-v line=3: Means creating awk variable named line whose value is 3 here as per your post.

FNR==line: Checking condition here if line number(awk's out of the box variable) value is equal to variable line value.

{next}: If condition mentioned above is TRUE then putting next will skip all further statements and nothing will happen on 3rd line of Input_file.

1: awk works on method of condition and action so by mentioning 1 making condition as TRUE and not mentioning any action so by default print of line will happen.

In case you want to save output into same Input_file itself then append > temp_file && mv temp_file Input_file to above code too.


Or with sed in case -i option is not there.

sed '3d' Input_file > temp_file && mv temp_file Input_file

POSIX sed page:

http://pubs.opengroup.org/onlinepubs/9699919799/utilities/sed.html

RavinderSingh13
  • 130,504
  • 14
  • 57
  • 93
  • Well, I already knew the `sed` command. The question is if there's a single command that can do the job, instead of squashing all the commands in a single line with `&&`s or `;`s. – Luis Lavaire. Jul 13 '18 at 15:52
  • @LuisLavaire, since you told `-i` option is not working so that is work around for it, also I added explanation to now, let me know? – RavinderSingh13 Jul 13 '18 at 15:53
  • It's not that it doesn't work: it's that the `-i` flag is (specific?) for the GNU's `sed`. I need to make my script POSIX-compliant. – Luis Lavaire. Jul 13 '18 at 15:57
  • @LuisLavaire, since I don't have POSIX `sed` with me so can't confirm but after searching seems like it is not there see this http://pubs.opengroup.org/onlinepubs/9699919799/utilities/sed.html – RavinderSingh13 Jul 13 '18 at 16:04
  • As you can see, the `-i` flag is not specified by POSIX. – Luis Lavaire. Jul 13 '18 at 17:17
  • 1
    Like `sed`, Awk doesn't support overwriting the destination file (though GNU Awk has an option for this); so this has the same flaw as `sed` without `-i`. – tripleee Jul 16 '18 at 12:55
2

A slightly shorter version then Ravinder his script is :

awk '(FNR!=3)' input_file

An awk program is composed of pairs of the form:

pattern { action }

Either the pattern or the action (including the enclosing brace characters) can be omitted. A missing pattern shall match any record of input, and a missing action shall be equivalent to: { print }.

The pattern in this case states checks If the line-number of the file (FNR) is different from 3. If true, perform the default action ({print $0}).

The deletion of the line would read then :

$ awk '(FNR!=3)' input_file > tmp_file && mv tmp_file input_file
kvantour
  • 25,269
  • 4
  • 47
  • 72
1
awk 'NR!=3{a[++nr]=$0} END{for (i=1;i<=nr;i++) print a[i] > FILENAME}' file
Ed Morton
  • 188,023
  • 17
  • 78
  • 185
  • 1
    Is it guaranteed that the entire file is read and closed prior to execution of `END` then? – Mark Setchell Jul 13 '18 at 21:45
  • 1
    It is guaranteed that the entire file is read, whether or not it's closed I couldn't find in the POSIX spec given how much time I was willing to spend looking at it. It's also guaranteed that it will be opened by `>` if not already open. – Ed Morton Jul 13 '18 at 23:53
1

I am unsure about POSIX compliance, but can suggest using ed to delete the third line of a file as follows:

echo $'3d\nwq' | ed -s YourFile

or, maybe

printf "3d\nwq\n" | ed -s YourFile
Mark Setchell
  • 191,897
  • 31
  • 273
  • 432
  • The use of `printf` should be strongly preferred over `echo` if portability is a concern. `$'...'` C-style strings are a Bash extension, and not supported in POSIX. – tripleee Jul 16 '18 at 12:52
  • @MarkSetchell I didn't needed to use `$'...'`. I just used `echo '3d\nwq' | ed -s file`. @tripleee, why should `printf` be preferred over `echo`? – Luis Lavaire. Jul 17 '18 at 15:03
  • 1
    Requiring `echo` to support `\n` isn't portable, either. The many incompatible versions of `echo` is precisely the reason you should use `printf` instead, which is strictly specified by POSIX. (Embedding a literal newline between the quotes should work fine with all versions of `echo` too, though.) – tripleee Jul 17 '18 at 16:42