-1

I have the following xdotool output from the shell:

Window 98566146
  Position: 5,279 (screen: 0)
  Geometry: 960x480

I want it to be :

 x=5
 y=279
 width=960
 height=480

with awk, sed, or other tools.

CLARIFICATION: I want to format output of xdotool search --sync --class mpv getwindowgeometry the way I described above using regular expression replace techniques via awk, sed or other tools. There is an example in the following link sed/awk replace a specific pattern under another pattern.

Such as

echo -e "Window 98566146\n  Position: 5,279 (screen: 0)\n  Geometry: 960x480\n" | awk ....

EDIT2:

Actually I could try the following awk line:

  echo -e "Window 98566146\n  Position: 5,279 (screen: 0)\n  Geometry: 960x480\n" |  awk -F'[:]' '{if (NR>1) print $2}'
0

6 Answers 6

3
$ awk -v RS= -F'[[:space:]:,x]+' '{printf "x=%d\ny=%d\nwidth=%d\nheight=%d\n", $4, $5, $9, $10}' file
x=5
y=279
width=960
height=480
3
2

You can also do it with this somewhat rudimentary approach, using tr and relying on shell word splitting:

$ alias XDR='echo -e "Window 98566146\n  Position: 5,279 (screen: 0)\n  Geometry: 960x480\n"'
$ XDR | tr -dc '0-9 ,x' | tr ' ,x' ' '

which returns

98566146   5 279  0   960 480

then just feed it to the shell - I'd suggest using ( ) to protect the current environment:

$ (set $(XDR | tr -dc '0-9 ,x' | tr ' ,x' ' ') &&\
   echo -e "x=$2\ny=$3\nwidth=$5\nheight=$6")

or in bash, use process substitution to pull it directly into variables:

$ read wid x y scr width height < <(XDR | tr -dc '0-9 ,x' | tr ' ,x' ' ')
$ echo -e "x=$x\ny=$y\nwidth=$width\nheight=$height"

update - the following works just as well:

$ XDR | tr -c '0-9' ' '
4
  • 1
    I just tried it, it works. I like creative ideas. I didn't expect such an innovative approach though I sensed it intuitively. Thank you.
    – kenn
    May 26, 2021 at 7:45
  • 1
    I've sensed I miss something, it can be done with only one simple tr: tr -c 0-9 ' '
    – mwy
    May 27, 2021 at 10:18
  • Can you please explain your inventive approach? Especially the use of the te utility.
    – guest_7
    May 28, 2021 at 20:28
  • I'd suggest running tr --help, all you need to know about it is there. One of the simplest, yet most useful tools at hand on any posix console. Play around with it. Do ls -l / | tr a-z A-Z, then do ls -l / | tr -d a-z, or something like ls -l / | tr -cd 'a-z\n'. You'll get the idea.
    – mwy
    May 31, 2021 at 4:49
1

There are lots of ways to do this. Here's a really basic method:

$ awk -F'[:,x]' '/Position:/ { sub(" .*","",$3); printf "x=%i\ny=%s\n", $2,$3};
                 /Geometry:/ { printf "width=%i\nheight=%i\n", $2, $3}' xdotool.txt 
x=5
y=279
width=960
height=480

This uses either a colon, a comma, or an x as the field separator. It also uses sub() to remove the space character and everything after it from the y value ($3) on the Position: line.

xdotool.txt is a text file that contains your example xdotool output.

3
  • If you use y=%d instead of y=%s then you don't need the sub(" .*","",$3); since awk will strip everything after the leading numeric part anyway in the process of converting $3 from a string to a number for printing with %d.
    – Ed Morton
    May 24, 2021 at 14:19
  • I like to do things explicitly rather than rely on side-effects. especially when i'm trying to teach someone how to do something. side-effects are a potential source of confusion that just create distracting questions that detract from what is being taught.
    – cas
    May 24, 2021 at 14:40
  • Sounds good, then you should add sub(/ /,"",$2) to the Geometry line to explicitly strip the blank from the front of $2 that THAT conversion to a number (for %i ) is currently stripping as a side-effect.
    – Ed Morton
    May 24, 2021 at 14:53
1

Another way to do this using awk can be firstly, setting FS for getting the data of interest into a field, $2 in this case:

awk -F'^ +Position: |^ +Geometry: |[()]'  'NR>1{print $2}' file
5,279
960x480

Secondly, we can split the data records 2 and 3 with split() function and print them adding the prefixes you need:

awk -F'^ +Position: |^ +Geometry: |[()]'  '
   NR == 2 {split($2, a, /,/);print "x="a[1]"\ny="a[2]}
   NR == 3 {split($2, a, /x/);print "width="a[1]"\nheight="a[2]}
' file
x=5
y=279
width=960
height=480
2
  • My knowledge of awk is basic. I didn't know how to replace text. AWK is a treasure. Your answer is detailed. Thank you.
    – kenn
    May 23, 2021 at 14:23
  • You are right, awk is a treasure, sometimes easy and sometimes not so, but always efficient for managing text. I learn something every day I use it. May 23, 2021 at 17:38
1

Tested with GNU sed and busybox sed:

sed -nEe 's/^[[:space:]]+Position: ([[:digit:]]+),([[:digit:]]+) \(screen: 0\)$/x=\1\ny=\2/p' -e 's/^[[:space:]]+Geometry: ([[:digit:]]+)x([[:digit:]]+)$/width=\1\nheight=\2/p'
1

We implement hashes in sed using GNU version of the sed editor in extended regex mode -E

fmt=',x=%d\ny=%d\nxwidth=%d\nheight=%d'
sed -En '
  1{x;s/.*/'"$fmt"'/;x;}
  /Position:|Geometry:/G
  s/.*\s([0-9]+)([x,])([0-9]+)\s.*\n\2([^=]+=)%d([^=]+=)%d.*/\4\1\5\3/p
' file
x=5
y=279
width=960
height=480

Another method is using python and nested list comprehension:

python3 -c 'import sys
## separator based on first field
s = { "Position:" : ",",
      "Geometry:" : "x" }

## string format based on first field
f = { "Position:" : "x={}\ny={}",
      "Geometry:" : "width={}\nheight={}" }

with open(sys.argv[1]) as fh:
  print(*[f[f0].format(*(f1.split(s[f0]))) for l in fh for f0,f1 in [l.strip().split()[0:2]] if f0 in f],sep="\n")
' file

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.