Score:0

How to change the bash code to get still the screen resolution on ubuntu by xrandr, but without to use awk?

ng flag

The follow bash code are well working to get and echo the x an y resolution of a screen by unseeing xrandr:

You can get your current screen's resolution as follows:

Get the X resolution by running:

X=$(xrandr --current | grep '*' | uniq | awk '{print $1}' | cut -d 'x' -f1)

Get the Y resolution by running:

Y=$(xrandr --current | grep '*' | uniq | awk '{print $1}' | cut -d 'x' -f2)

Output the X and Y resolution by running:

echo "$X"x"$Y"

or

echo "$X"
echo "$Y"

How to change this code to get the screen resolution on ubuntu, still by unseeing xrandr, a without to use awk ?

hr flag
IMHO it would make more sense to keep awk and lose the other commands ex. `awk '/\*/{split($1,a,"x"); print a[2]; exit}'`
Eddy763 avatar
ng flag
awk is not available on all systems...
muru avatar
us flag
On which Ubuntu systems is it not available? Even `ubuntu-minimal` depends on it. The standard Ubuntu Docker images, which are also pretty minimal, have it.
Score:4
cn flag

First of all, there really is no reason to remove awk. It is extremely fast, stable and made for this sort of thing. However, your command is needlessly complicated. You could simply do:

$ xrandr --current | awk '$2~/\*/{print $1}' 
2560x1440

If you really need the x and y separately, do:

x=$(xrandr --current | awk '$2~/\*/{print $1}' | cut -d'x' -f1)
y=$(xrandr --current | awk '$2~/\*/{print $1}' | cut -d'x' -f2)
echo "$x"
echo "$y"

Or, more simply:

$ read x y < <(xrandr --current | awk '$2~/\*/{sub(/x/," ");print $1,$2}')
$ echo "x:$x y:$y"
x:2560 y:1440

And if you insist on not using awk, here are a few other options:

read x y < <(xrandr --current | sed -En '/\*/{s/^ *([0-9]+)x([0-9]+).*/\1 \2/p}')
echo "$x"
echo "$y"

or

read x y < <(xrandr --current | perl -lne 'print "$1 $2" if /^ *([0-9]+)x([0-9]+).*/')
echo "$x"
echo "$y"

or

read x y < <(xrandr --current | grep -oP '\d+x\d+' | tr x ' ')
echo "$x"
echo "$y"

Note that all of these assume only one screen is connected, as does your original approach.

terdon avatar
cn flag
@Eddy763 don't worry about it :) However, if one of the answers here solved your issue, please take a moment and [accept it](//askubuntu.com/help/someone-answers) by clicking on the checkmark on the left. That is the best way to express your thanks on the Stack Exchange sites.
hr flag
Another `read` based option might be something like `IFS=' x' read x y _ < <(xrandr --current | grep -F '*')` - with space as the first character of IFS it strips leading whitespace, then splits on `x` as well
terdon avatar
cn flag
@Eddy763 great! I sort of assumed that was implied and didn't want to repeat it on every solution.
cn flag
@terdon You could use *pure bash*: Have a look at [my answer](https://askubuntu.com/a/1453951/295207)
terdon avatar
cn flag
@F.Hauri-GiveUpGitHub yes, of course you _can_ if you want. By why would anyone want to use a much slower tool with even more complicated syntax? Even in embedded systems, the basic POSIX tools are usually available, and certainly in all Ubuntu flavors, so using bash is no advantage. It just makes things slower and more complicated for no benefit. I mean, you could also do this in C but would you want to? :)
cn flag
You are wrong: parsing small outpuit like `xrandr` is a lot quicker in a small loop, rhan if you ***fork*** to awk, or any other tool.
terdon avatar
cn flag
@F.Hauri-GiveUpGitHub actually, despite your aggressive tone, I am not wrong. Did you test it? I ran your first shell loop 20 times and it took an average of 0.024 seconds while my first awk solution took an average of 0.0005 seconds. You are probably thinking of cases like basic string manipulation of a variable where doing it in the shell might be faster but as soon as you bring in a shell loop or `read` everything is much slower. This is all nicely explained here: [Why is using a shell loop to process text considered bad practice?](https://unix.stackexchange.com/q/169716).
cn flag
Sorry for the tone, Anyway please, have a look : [`awk` vs `bash` loop compariso](!https://www.jdoodle.com/iembed/v0/DBA) Paste your `xrandr` output as *`Stdin Inputs`* and compare...
cn flag
Or there: https://onlinegdb.com/59akE2Rvu
terdon avatar
cn flag
@F.Hauri-GiveUpGitHub I don't understand. Why would I use some online GUI for this? And how can I use that to test simple command line executions as I showed here? You can test both approaches trivially on your machine, just run them with `time`. I'm happy to play with this more [in chat](https://chat.stackexchange.com/rooms/201/ask-ubuntu-general-room) if you want. Ping me.
Score:2
cn flag

You can use a binary operator and read:

[[ $(xrandr --current) \
    =~ current\ ([0-9]+)\ x\ ([0-9]+) \
]] && read x y <<< "${BASH_REMATCH[@]:1:2}"

echo ${x}x${y}

The second variant creates a stride list with current modes.

#!/bin/bash

a=()
while read -r; do
    [[ $REPLY \
    =~ \ +([0-9]+)x([0-9]+)\ +[0-9.]+\* ]] && a+=(${BASH_REMATCH[@]:1:2})
done < <(xrandr --current)

# print the first resolution.
read x y <<< ${a[@]::2} && echo ${x}x${y}
Score:0
cn flag

Parsing xrandr output

In this answer I use pure bash. All proposed solution do xrandr output parsing without any call to external binary like awk, grep, etc.

Instead of grep for star *, simply grep for connected line:

xrandr --current | grep connected
VGA-1 disconnected (normal left inverted right x axis y axis)
DP-1 disconnected (normal left inverted right x axis y axis)
HDMI-1 connected primary 1920x1080+0+120 (normal left inverted right x axis y axis) 531mm x 299mm
DP-2 connected 1920x1200+1920+0 (normal left inverted right x axis y axis) 535mm x 339mm
HDMI-2 disconnected (normal left inverted right x axis y axis)

This show which screen is connected and his current size:

Showing screens

scnt=1
while IFS=' x+' read dev stat w h x y j _; do
    if [[ $stat == connected ]]; then
        typ=sec
        [[ $w == primary ]] &&
            typ=${w::3} w=$h h=$x x=$y y=$j
        printf '%3d: %-8s (%s) width:%5d height:%5d hoffset:%5d voffset:%5d\n' \
            $((scnt++)) $dev $typ $w $h $x $y
    fi
done < <(xrandr)
  1: HDMI-1   (pri) width: 1920 height: 1080 hoffset:    0 voffset:  120
  2: DP-2     (sec) width: 1920 height: 1200 hoffset: 1920 voffset:    0

Or full parsing display and screens:

scnt=1
while read -r line; do
    case $line in 
        Screen*)
            line=${line#*current }
            IFS=' ,' read -r width _ height _ <<< "$line"
            printf '%-20swidth:%5d height:%5d\n' Whole\ display: $width $height
        ;;
        *\ connected\ *)
            IFS=' x+' read -r dev stat width height offx offy j _ <<< "$line"
            typ=sec
            [[ $width == primary ]] &&
                typ=${width::3} width=$height height=$offx offx=$offy offy=$j
            printf '%3d: %-8s (%s) width:%5d height:%5d hoffset:%5d voffset:%5d\n' \
                $((scnt++)) $dev $typ $width $height $offx $offy
        ;;
    esac
done < <(xrandr)

This will show on my host:

Whole display:      width: 3840 height: 1200
  1: HDMI-1   (pri) width: 1920 height: 1080 hoffset:    0 voffset:  120
  1: DP-2     (sec) width: 1920 height: 1200 hoffset: 1920 voffset:    0
mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.