Необходимо включить extglob
:
#!/bin/bash
shopt -s extglob
cat ~/my/+(a|b)/doc
+()
расширенный шаблон, только распознан когда extglob
включен. По умолчанию extglob
идет в интерактивных оболочках и прочь в неинтерактивных оболочках.
Как насчет (принятие Вашей оболочки имеет замену процесса):
for file in "${filelist[@]}"; do
cat <(printf "%s" "$prefix") "$file" <(printf "%s" "$suffix") > "$file"_$$\
&& mv "$file"_$$ "$file"
done
или, лучше, в (непротестированном) Perl:
perl -MTie::File -e '
@ARGV//=<STDIN>;
chomp(@ARGV);
for(@ARGV){
tie @lines,"Tie::File",$_;
@lines=($ENV{prefix} @lines $ENV{suffix})
}' "${filelist[@]}"
Для альтернативного подхода, если префикс и суффикс фиксируются, видят следующий вопрос (который также, оказывается, о TEX (La) :)):
С zsh:
zmodload zsh/mapfile
for i ($filelist) mapfile[$i]="$prefix
$mapfile[$i]$suffix
"
С ksh93
или bash
(или zsh
):
for file in "${filelist[@]}"; do
{
rm -- "$file" && {
printf '%s\n' "$prefix"
cat
printf '%s\n' "$suffix"
} > "$file"
} < "$file"
done
Вот несколько вариантов, ни один из которых не использует sed
. Я нахожу что в целом, пытаясь добраться sed
играть по правилам с внешними переменными редко стоит усилия.
for file in "${filelist[@]}"; do
tmp=$(mktemp);
printf "%s\n%s\n%s\n" "$prefix" $(cat "$file") "$suffix" > "$tmp" &&
mv "$tmp" "$file";
done
for file in "${filelist[@]}"; do
tmp=$(mktemp);
perl -lpe 'BEGIN{print $ENV{prefix}}END{print $ENV{suffix}}' $file
mv "$tmp" "$file";
done
Этот имеет преимущество не доверия внешним модулям:
perl -le 'foreach (@ARGV){
open($f,"+<","$_"); @a=<$f>;
print $f "$ENV{suffix}\n@a$ENV{prefix}"
}' "${filelist[@]}"
Переменные должны быть экспортированы для решений для Perl работать, иначе, они не будут доступны в %ENV
хеш.
Случай подобен этому: Добавление строки, содержащей символ ESC с sed
Я предлагаю тот же (адаптированный) ответ:
for file in "${filelist[@]}"; do
sed -i "1i\\
$(echo -E "$prefix" | sed -e 's/\\/\\\\/g' | sed -e '$! s/$/\\/')" "$file" &&
echo "$suffix" >> "$file"
done
sed
команда i
требует, чтобы каждая строка кроме последнего была завершена с обратной косой чертой (это отсутствовало в отнесенном ответе). Кроме того, обратные косые черты должны быть удвоены, таким образом, sed
не попытается интерпретировать их. echo
производит содержание переменной $prefix
. Затем в конвейере, sed
команда удваивает обратные косые черты. Второе sed
команда добавляет обратные косые черты в конце каждой строки кроме последнего.
ОТРЕДАКТИРУЙТЕ Как sed программа $! s/$/\\/
работы:
Во-первых, адрес $
средства выполнить команду, которая следует последняя строка. $!
инвертирует это, таким образом, команда будет выполняться на всех строках кроме последнего.
Затем s///
команда делает замену. Это заменит пустой строкой в конце строки, обозначенной $
, с обратной косой чертой. Но обратная косая черта является специальным символом, таким образом, мы должны выйти из нее с другой обратной косой чертой для sed
считать его правильно.
i
требует, чтобы каждая строка кроме последнего была завершена с обратной косой чертой и (b), что обратные косые черты должны быть удвоены? Наконец, если Вы вдаетесь в немного большее количество подробностей о как sed -e '$! s/$/\\/'
работы, которые были бы полезны.
– Faheem Mitha
25.01.2014, 14:26
a\
. (c) видят отредактированный ответ.
– angus
25.01.2014, 21:10
sed --version GNU sed version 4.2.1
. Какую версию Вы используете? В любом случае, нечетный. Я проверю снова в случае, если я сделал ошибку.
– Faheem Mitha
25.01.2014, 21:53