0

I'm trying to understand this great answer that explains how to implement "pop" command to a file using sed.

I build some test data with

printf "Line #%2d\n" {1..7} >file

then run

sed -e \$$'{w/dev/stdout\n;d}' -i~ file

I'm trying to figure out this sed command. Here what I came up with so far:

  1. -e

-e script, --expression=script add the script to the commands to be executed.

  1. This answer explains about /dev/stdout.

  2. \n means newline

  3. -i~

-i[SUFFIX], --in-place[=SUFFIX]

edit files in place (makes backup if extension supplied).

I still cannot understand it.

2 Answers 2

3

The first command creates a file with seven lines of text. This data is used by the SO answer to illustrate the effect of the sed command, and it is written to a file called file.

Given a shell that understands $'...' ("C-strings") and that you use GNU sed (to understand d} as d;}), the second command returns the last line from the test data file on standard output and removes it from the file, backing up the original data in file~ (backing up the original data to file~ is what -i~ does).

In the SO answer, the sed editing script is written on the command line as

\$$'{w/dev/stdout\n;d}'

This is a literal $, followed by a "C-string", $'{w/dev/stdout\n;d}'. The C-string quoting means \n will be expanded to a literal newline, which gives

${w/dev/stdout
;d}

... which is a sloppy way of writing the sed script

$ {
    w /dev/stdout
    d
}

This sed editing script passes all but the last line through unchanged to the output (which goes into the file file since the -i option is used).

The last line is written to /dev/stdout rather than to the default output (which is file in this case) using the w command, and then deleted using d.

The effect is that all lines but the last remain in (are written back to) file while the last line is produced on standard output (which will be connected to your terminal).

5
  • 1
    The first $ is part of the sed script, as it's not inside the quotes, it is escaped. The second $ is part of the shells ANSI-C quoting. You could also write: '${w/dev/stdout'$'\n'';d}' to make it clear that the $'...' is only needed for the \n. Commented Jan 5, 2022 at 7:36
  • man7.org/linux/man-pages/man1/file.1.html . -i, --mime Causes the file command to output mime type strings rather than the more traditional human readable ones. Thus it may say ‘text/plain; charset=us-ascii’ rather than “ASCII text”. Can your add reference link that explain -i~ file Commented Jan 5, 2022 at 7:42
  • @Mark file is the name of the input file, i.e. the file created by the first command in your question. It is not the file utility. This has nothing to do with mime-types. The name file is just used as a generic name for a file in this case. I tried to make that clear in the first paragraph of my answer: "a file called file". The -i option is an option to sed. Commented Jan 5, 2022 at 7:43
  • @they ~ normally refer to home directory [tilde]. I am not sure what does it mean? when it connect with i. Commented Jan 5, 2022 at 7:51
  • @Mark I've now added a clarification about -i~ in the text. It is common to back up files before making changes to them, and sed -i~ does this by copying the original data to a file with the original file's name with an added ~ at the end. If you try running the two commands in an otherwise emtpy directory, and look at the files created, it should be clear what's happening. Commented Jan 5, 2022 at 7:54
0

You got a good answer to the question you asked but FYI the best answer to "how to implement pop command to a file using sed" as in the question you referenced is "don't do that". I expect that question would have got that answer if it hadn't been quickly closed as unclear.

The following uses GNU awk instead of the GNU sed you're currently using, will work in any shell, and is hopefully much easier to understand:

$ awk -i inplace 'NR>1{print prev} {prev=$0} END{if (NR) print prev}' file
Line # 7

$ cat file
Line # 1
Line # 2
Line # 3
Line # 4
Line # 5
Line # 6

See https://www.gnu.org/software/gawk/manual/gawk.html#Extension-Sample-Inplace for more info on "inplace" editing with GNU awk.

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.