л.с.; ДР:
Есть несколько способов обойти это, я думаю, что самый чистый для вашего примера случай:
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
будет выполнено там .
Есть много способов сделать это. Вот действительно простой метод:
$ 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.
$ 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
Проверено с 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'
Мы реализуем хэши в 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
Вы также можете сделать это с помощью этого довольно примитивного подхода, используя 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' ' '