-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
  • 1
    Perfect use of RS and FS for getting the 4 fields! Commented May 24, 2021 at 5:46
  • 1
    @ed-morton Thank you for your help. Yours is the simplistic approach. I used your liner in my project here github.com/trappedinspacetime/mpv-save-window-position/blob/… Commented May 24, 2021 at 9:09
  • @kenn you're welcome. Commented May 24, 2021 at 14:04
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. Commented 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 ' ' Commented May 27, 2021 at 10:18
  • Can you please explain your inventive approach? Especially the use of the te utility. Commented 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. Commented 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. Commented 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. Commented 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. Commented 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. Commented 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. Commented 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

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.