Hi all! I have always only used sed with s///, becouse I’ve never been able to figure out how to properly make use of its full capabilities. Right now, I’m trying to filter the output of df -h --output=avail,source to only get the available space from /dev/dm-2 (let’s ignore that I just realized df accepts a device as parameter, which clearly solves my problem).

This is the command I’m using, which works:

df -h --output=avail,source \
    | grep /dev/dm-2 \
    | sed -E 's/^[[:blank:]]*([0-9]+(G|M|K)).*$/\1/

However, it makes use of grep, and I’d like to get rid of it. So I’ve tried with a combiantion of t, T, //d and some other stuff, but onestly the output I get makes no sense to me, and I can’t figure out what I should do instead.

In short, my question is: given the following output

$ df -h --output=avail,source 
Avail Filesystem
  87G /dev/dm-2
 1.6G tmpfs
  61K efivarfs
  10M dev
...

How do I only get 87G using only sed as a filter?

EDIT:

Nevermind, I’ve figured it out…

$ df -h --output=avail,source \
    | sed -E 's/^[[:blank:]]*([0-9]+(G|M|K))[[:blank:]]+(\/dev\/dm-2).*$/\1/; t; /.*/d'
85G
  • unlawfulbooger@lemmy.blahaj.zone
    link
    fedilink
    arrow-up
    4
    ·
    edit-2
    7 days ago

    The easiest way is probably without sed, which you mentioned:

    df -h --output=avail /dev/dm-2| tail -n1
    

    But purely with sed it would be something like this:

    df -h --output=avail,source | sed -n ‘/\/dev\/dm-2/s!/dev/dm-2!!p’
    

    -n tells sed to not print lines by default

    /[regex]/ selects the likes matching regex. We need to escape the slashes inside the regex.

    s/// does search-and-replace, and has a special feature: it can use any character, not just a slash. So I used three exclamation points instead , so that I don’t need to escape the slashes. Here we replace the device with the empty string.

    p prints the result

    Check the sed man page for more details: https://linux.die.net/man/1/sed

    • orsetto@lemmy.dbzer0.comOP
      link
      fedilink
      arrow-up
      2
      ·
      edit-2
      7 days ago

      !/dev/dm-2!!p

      This weired me out until I read the explanation. I’m so used to the slashes lol

      In the end I’ve used the first command you wrote, because KISS, but I appreciate your explanation

      Check the sed man page for more details

      Yes that’s been my only source so far, but to be honest it’s really cryptic. it might just be that I’m used to syscalls man pages (also sed is language so it can’t be easy to write a single man page for it)

      • unlawfulbooger@lemmy.blahaj.zone
        link
        fedilink
        arrow-up
        1
        ·
        7 days ago

        In the end I’ve used the first command you wrote, because KISS, but I appreciate your explanation

        There’s no shame in combining multiple tools, that’s what pipelines are all about 😄.

        Also there’s a different tool that I would use if I want to output a specific column: awk

        df -h —output=avail,source | awk ‘/\/dev\/dm-2/ {print $1}’
        

        For lines matching /dev/dm-2 print the first column. awk splits columns on whitespace by default.

        But I would probably use grep+awk.

        Sed is definitely a very powerful tool, which leads to complex documentation. But I really like the filtering options before using the search/replace.

        You can select specific lines, with regex or by using a line number; or you can select multiple lines by using a comma to specify a range.

        E.g. /mystring/,100s/input/output/g: in the lines starting from the first match of /mystring/ until line 100, replace input with output