
Я могу найти много вопросов с ответами в другом направлении, но, к сожалению, не в том, в котором я хотел бы, чтобы мои замены: Я намерензаменить символ, такой как #
,в строке, например test#asdf
, с последовательностью, например{0..10}
чтобы получить последовательность строк, в этом примере test0asdf test1asdf test2asdf test3asdf test4asdf test5asdf test6asdf test7asdf test8asdf test9asdf test10asdf
.
Я пробовал, из других:
echo '_#.test' | tr # {0..10}
(бросает использование)echo '_#.test' | sed -r 's/#/{0..10}/g'
(возвращается_{0..10}.test
)echo '_#.test' | sed -r 's/#/'{0..10}'/g'
(работает для первого раза, потом получаюsed: can't read (...) no such file or directory
)
Каков рабочий подход к решению этой проблемы?
Редактировать, так как я пока не могу комментировать: мне нужно использовать #
в строке, в которой этот символ должен быть заменен, поскольку строка передана из другой программы. Я мог бы сначала заменить его другим символом, хотя.
решение1
Оператор {0..10}
zsh
(теперь также поддерживаемый несколькими другими оболочками, включая bash
) — это просто еще одна форма csh
расширения фигурных скобок в стиле -.
Он расширенпо оболочкеперед вызовом команды. Команда их не видит {0..10}
.
With tr '#' {0..10}
(заключив это в кавычки, #
так как в противном случае оболочка интерпретирует это как начало комментария), tr
в конце вызывается с аргументами ("tr", "#", "0", "1", ..., "10") и tr
не ожидает такого количества аргументов.
Здесь вам понадобится:
echo '_'{0..10}'.test'
для echo
передачи "_0.test", "_1.test", ..., "_10.test" в качестве аргументов.
Или, если вы хотите, чтобы это #
было преобразовано в этот {0..10}
оператор, преобразуйте его в код оболочки для оценки:
eval "$(echo 'echo _#.test' | sed 's/#/{0..10}/')"
где eval
передается echo _{0..10}.test
в качестве аргументов.
(не то чтобы я рекомендовал делать что-то подобное).
решение2
Ты можешьрасколотьстроку на разделителе, захватите префикс и суффикс, затем используйте раскрытие фигурных скобок для генерации имен:
str='test#asdf'
IFS='#' read -r prefix suffix <<<"$str"
names=( "$prefix"{0..10}"$suffix" )
declare -p names
declare -a names='([0]="test0asdf" [1]="test1asdf" [2]="test2asdf" [3]="test3asdf" [4]="test4asdf" [5]="test5asdf" [6]="test6asdf" [7]="test7asdf" [8]="test8asdf" [9]="test9asdf" [10]="test10asdf")'
решение3
Вам обязательно использовать #
? Может быть, вы могли бы использовать %d
?
$ for i in {1..10}; do printf "_%d.test " "$i"; done
_1.test _2.test _3.test _4.test _5.test _6.test _7.test _8.test _9.test _10.test
решение4
Я бы сделал это срасширение параметра:
$ var='test#asdf'
$ for i in {1..10}; do echo "${var/\#/"$i"}"; done
test1asdf
test2asdf
test3asdf
test4asdf
test5asdf
test6asdf
test7asdf
test8asdf
test9asdf
test10asdf
Расширение${parameter/pattern/string}
- принимает расширение (в нашем случае, ) и
$parameter
$var
- заменяет первое вхождение
pattern
(экранированный#
–/#
имеет особое значение в контексте, «заменить в начале строки», чего мы хотим избежать) с string
("$i"
в нашем случае)
В качестве альтернативы вы можете заменить #
на %d
и использовать его в качестве строки формата для printf
:
printf "${var/\#/%d}\\n" {1..10}