Как заменить один символ, чтобы получить много строк в Shell?

Как заменить один символ, чтобы получить много строк в Shell?

Я могу найти много вопросов с ответами в другом направлении, но, к сожалению, не в том, в котором я хотел бы, чтобы мои замены: Я намерензаменить символ, такой как #,в строке, например 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}

Связанный контент