Форматирование вывода геометрии окна xdotool

л.с.; ДР:

Есть несколько способов обойти это, я думаю, что самый чистый для вашего примера случай:

for i in {1..5};do sed -i "s/abc/$(seq -s ' ' 1 $i)/g" test; done

То есть :мы просим seqиспользовать один единственный пробел для разделения каждого числа.

Пояснение:

Причина, по которой вы получили эти ошибки, заключается в том, что вывод из:

seq 1 5

не является:

1 2 3 4 5

а скорее:

1
2
3
4
5

А поскольку вы заключили$(seq 1 $i)Подстановку команд в двойные -кавычки, обычное Разбиение слов не выполняется, следовательно, все символы новой строки (, кроме последней )выходные данные утилиты seqостаются без изменений.

Поэтому фактическая sedкоманда стала:

sed -i "s/abc/1
2
3
4
5
/g" test

который не принят, потому что, что касается sed , вы предоставили его с командой s/abc/1, т. е. без требуемого финального /.

echo $(seq 1 5)печатает 1 2 3 4 5, потому что $(seq 1 5)не находится в двойных -кавычках, поэтому разделение слов происходит в соответствии с поведением оболочки по умолчанию.

Мы действительно можем исправить ваш пример, как и в:

for i in {1..5};do sed -i "s/abc/$(echo $(seq 1 $i))/g" test; done

, то есть путем замены команды (исходнойseq 1 $i)внутри другой замены команды (на echoна ).

Это работает даже в двойных -кавычках, потому что $(echo...)Подстановка команд выполняется в подоболочке , которая не в «Я -есть -] внутри -состояния -двойная -кавычка", поэтому разделение слов на выходе изseqбудет выполнено там .

-1
23.05.2021, 17:16
5 ответов

Есть много способов сделать это. Вот действительно простой метод:

$ 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

В качестве разделителя полей используется двоеточие, запятая или x. Он также использует sub()для удаления символа пробела и всего, что после него, из значения y ($3 )в строке Position :.

xdotool.txt— это текстовый файл, содержащий ваш пример вывода xdotool.

1
28.07.2021, 11:30
$ 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
28.07.2021, 11:30

Проверено с GNU sedи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
28.07.2021, 11:30

Мы реализуем хэши в sed, используя версию GNU редактора sed в расширенном режиме регулярных выражений-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

Другой метод заключается в использовании Python и понимания вложенных списков:

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
1
28.07.2021, 11:30

Вы также можете сделать это с помощью этого довольно примитивного подхода, используя trи полагаясь на разбиение слова оболочки:

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

, который возвращает

98566146   5 279  0   960 480

затем просто передать его оболочке -Я бы предложил использовать()для защиты текущей среды:

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

или в bash используйте подстановку процесса, чтобы вставить его непосредственно в переменные:

$ 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"

обновление-следующее работает так же хорошо:

$ XDR | tr -c '0-9' ' '
2
28.07.2021, 11:30

Теги

Похожие вопросы