Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

    sed -i 
Watch out, that's a Linux-ism and macOS's sed will cheerfully use the thing after it as the backup expression; as far as I know, the absolute safest choice is to always specify a backup extension "sed -i~" or "sed -i.bak" to make it portable, although there are plenty of work-arounds trying to detect which is which and "${SED_I} -e whatever" type silliness

My contribution (and yeah, I know, PR it ...) is that I get a lot of mileage out of setting the terminal title from my scripts:

    title() { printf '\033]0;%s\007' "$*"; }
and there's one for tmux, too

    printf '\033]2;%s\007' "$*";
with the two infinitely handy resources:

* https://www.xfree86.org/current/ctlseqs.html

* https://iterm2.com/documentation-escape-codes.html



Even better, use a real text editor like ed or ex. (Nowadays ex is more portable because many distros — against POSIX — omit all 55 kilobytes of GNU ed. Of course, smaller systems might not have ex/vi.)

Basic usage looks like this:

    printf '%s\n' '" some commands...' 'wq' | ex -s file
Or:

    ex -s file <<'EOF'
    " some commands...
    wq
    EOF
By the way, these commands are the ones that you use in your vimrc or after a colon in vim — at least, the POSIX subset of that — so any ex commands you learn translate naturally to your normal editor.


That's an interesting trick, I'll bear it in mind.

That said, the "lottery factor" is often a bigger contributor to the things that land in codebases than "optimality". Plus, I've actually seen somewhere that perl is the most common binary across every system, and it's likely a larger population who know perl than ed would be my guess


With Perl, you can't just say "Perl", you have to be specific to which version of Perl.


What do you mean?


How many major versions of Perl do you know about?

What is the distribution of these different versions of Perl across various OSes and OS versions?

Hint: Lots of backward-incompatible changes tend to get made around different major versions. Having Perl 4 is not like having Perl 5 which is not like Perl 6.


I still don't know what your point is.

Are there any contemporary distros that have the "perl" exectuable that is not Perl 5?


If you want to claim broad compatibility, you can't just look at the latest distributions. You have to look at OSes other than Linux. You have to look at older versions of OSes, too. And don't forget the billions of embedded and handheld devices, too.


> You have to look at older versions of OSes, too.

Perl 5 was released in 1994. It is incredibly portable. If you have a system that legitimately has Perl 4, I would love to hear about it, but …


Perl more common than vi? The study you’re remembering probably didn’t include POSIX utilities.


With the full understanding that "docker images" are their own special little things:

    $ docker run --rm ubuntu:22.04 bash -c 'command -v ex; command -v ed; command -v vi; command -v perl;' 
    /usr/bin/perl
and the same result for "debian:stable"

---

edit: I just realized that's because apt is _written in_ perl, but tomato, tomahto, and it may very well be that they picked perl for that same universal-binary reason


Huh, interesting.


> Watch out, that's a Linux-ism and macOS's sed

It's GNU sed vs (Free)BSD sed, which are different enhancements of the POSIX standards for sed that went in different design directions. One could Homebrew/macports install gnu-sed on macOS to get a GNU version to write Linux-portable scripts as-needed.


Plan9 sed has no -i option. Older versions of NetBSD will not have it either.

I never understood the point of the -i option other than to conserve keystrokes. A temporary file is still created then removed; the -i option only saves the user from having to specify it. Maybe the intent is it is only for "one-off" use, not for use in scripts.

This will work for GNU, BSD and Plan9:

   sed -n 's/old/new/wfile.tmp' file
   mv file.tmp file
Or just use redirection.

Given the choice between avoiding some keypresses and more portable scripts, I will keep choosing the later.

NetBSD sed may have the -i option now but I do not see anyone using it in scripts meant to be portable, like build.sh^1

1. https://ftp.netbsd.org/pub/NetBSD/NetBSD-release-9/src/build...


Yeah, I've heard that argument, too, but I fear that ship has sailed

Also, be aware you currently have duplicated comments: https://news.ycombinator.com/item?id=31254181


> sed -n 's/old/new/wfile.tmp' file

This saves only lines which underwent substitution, which was probably not what you wanted.


Missing semicolon.

  sed -n 's/old/new/;w file.tmp' file
Unlike BSD and GNU sed, it appears that Plan9 sed will append to instead of overwite file.tmp

It also requires a space after the w command.


sed -i alone overwrites a soft or hard link with the contents of the file.


-i creates a temporary file and then replaces the original with the temporary. The BSD man page advises not to use -i alone because if there is insufficient space to store the temporary, data may be lost.


Using raw escape codes is ugly and device-dependent. People learned this in the 1970’s, and created libraries to get away from having to hard-code escape codes.

Here’s a device-independent variant:

  title(){ tput tsl || tput -T xterm+sl tsl; printf %s "$*"; tput fsl || tput -T xterm+sl fsl; }
Note: if the terminal does not advertise support of the necessary capabilities, it falls back to using the XTerm escape sequences.


Having arrived back at my Mac, running iTerm2, I wanted to share another fun fact about using those executables: running that function while the outer shell is in "set -x" causes the title of the window to be

    + printf %s 'hello world'^M^Jhello world+ tput fsl^M^J+tput -T xterm
and that's where it cuts off but I presume ends with "^M^J" at the end :-D


As a point of comparison, I ssh-ed into my mac and ran "tput -T xterm+sl tsl" in order to see what it would output, and it hung my connection

So, I'll stick to my printf thanks


You can’t run only one of the tput commands! You need to run both of them, as in the shell function; i.e. both tsl and fsl needs to be sent to the terminal!

If you want to see what bytes it would output, use “od”:

  tput -T xterm+sl tsl | od -t c


Yeah, I actually thought about that afterward, however, in that same "I wonder what happened", I also wondered if tput is bright enough to know the difference between the local termcap and the connected one

As a concrete example, my printf version works even when run inside docker, but

    $ docker run --rm ubuntu:22.04 bash -c '{ tput tsl || tput -T xterm+sl tsl; } | od -c'
    tput: No value for $TERM and no -T specified
    tput: unknown terminal "xterm+sl"
    0000000


Your example suffers from being a toy example; it makes no sense to run a noninteractive command in a docker container merely to output terminal escape codes. If this were the norm, "docker run” would probably by default make sure to copy the TERM setting to the inner command.

I would assume that if you run an interactive shell inside docker, TERM would actually be set correctly. It’s the same when you ssh somewhere else – the TERM environment variable is sent along, so that the remote program can see it and output the correct codes for your local terminal. Also, the docker image needs the terminfo database installed for “tput” to work.


Yeah please do open PRs for these!




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: