Вот еще один подход awk
:
$ awk '{a[$4]=0;a[$5]=1; for(i=6;i<=NF;i++){$i=a[$i]}}1;' file
1 rs6687776 1020428 T C 0 1 0 1 1 1 0 1 1 1 0 1
a [$ 4] = 0 ; a [$ 5] = 1;
: создает массив a
с двумя ключами, $ 4
и $ 5
. Для $ 4
установлено значение 0
, а для $ 5
- 1. для (i = 6; i <= NF; i ++) { $ i = a [$ i]}
: для каждого номера поля от 6 до последнего установите для этого поля значение, хранящееся в массиве для найденного нуклеотида.
1;
: сокращение от awk для «распечатать эту строку».
Вы также можете сделать это с помощью Perl:
$ perl -lane 's/$F[3]/0/ for @F[5..$#F]; s/$F[4]/1/ for @F[5..$#F]; print "@F"' file
1 rs6687776 1020428 T C 0 1 0 1 1 1 0 1 1 1 0 1
Это та же идея. -a
заставляет perl
действовать как awk
, разбивая каждую строку на пробелы в массив @F
. Затем мы заменяем все варианты нуклеотида, найденные в 4-м поле ( $ F [3]
, массивы начинаются с 0), на 0
и все варианты 5-го ( $ F [4]
) с 1
. для @F [5 .. $ # F]
означает, что замена применяется только к полям с 6 до последнего. Наконец, печатается измененный массив.
Данные, введенные пользователем one
, two
,three
Следующая команда заменит все экземпляры данного ${placeholder}
вашим вводом:
sed -i 's/${placeholders}/one/g; s/${different}/two/g; s/${here}/three/g' yourTemplateFile
Если вы используете это в скрипте bash и вводите пользовательский ввод в переменных оболочки, это сделает все замены в одной команде.
Вот как это сделать в bash. Вам нужна последняя версия, потому что здесь я полагаюсь на ассоциативные массивы
template=$(cat << 'END_TEMPLATE'
I have some
text with ${placeholders}
in this and some ${different}
ones ${here} and ${there}
END_TEMPLATE
)
mapfile -t placeholders < <(grep -Po '(?<=\$\{).+?(?=\})' <<< "$template" | sort -u)
declare -A data
for key in "${placeholders[@]}"; do
read -p "Enter the '$key' value: " -r data[$key]
done
t=$template
while [[ $t =~ '${'([[:alnum:]_]+)'}' ]]; do
t=${t//"${BASH_REMATCH[0]}"/"${data[${BASH_REMATCH[1]}]}"}
# ^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
# | + the value the user entered
# + the placeholder in the text
done
echo "$t"
Предполагая [a] , что ни \<новая строка>, ни символы \
, $
или `
не используются в многострочной строке (или они правильно заключены в кавычки ), здесь -документ (и переменные )— ваш лучший вариант:
#!/bin/sh
placeholders="value one"
different="value two"
here="value three"
there="value four"
cat <<-_EOT_
I have some
text with ${placeholders}
in this and some ${different}
ones ${here} and ${there}.
_EOT_
При выполнении:
$ sh./script
I have some
text with value one
in this and some value two
ones value three and value four.
Конечно, правильно играя с кавычками, можно было бы обойтись даже одной переменной:
$ multilinevar='I have some
> text with '"${placeholders}"'
> in this and some '"${different}"'
> ones '"${here}"' and '"${there}"'.'
$ echo "$multilinevar"
I have some
text with value one
in this and some value two
ones value three and value four.
Оба решения могут принимать многострочные переменные-заполнители.
[а] Из инструкции:
... the character sequence \<newline> is ignored, and \ must be used to quote the characters \, $, and `....
Протестировано с помощью приведенного ниже сценария, все работает нормально
echo "enter count of userinput required"
read c
for ((i=1;i<=$c;i++))
do
echo "enter the values"
read input_$i
done
awk -v i="$input_1" -v j="$input_2" -v k="$input_3" -v l="$input_4" '{gsub(/\${placeholders}/,i,$0);gsub(/\${different}/,j,$0);gsub(/\${here}/,k,$0);gsub(/\${there}/,l,$0);print $0}' filename >>filename_tmp && mv filename_tmp filename