Поскольку переменная не задается вашим документом:
$ VALUE=<<PERSON
> {
> "type": "account",
> "customer_id": "1234",
> "customer_email": "jim@gmail.com",
> }
> PERSON
$ echo "$VALUE"
$
Если вы хотите использовать heredoc для присвоения значения переменной, вам понадобится что-то вроде:
$ read -d '' -r VALUE <<PERSON
{
"type": "account",
"customer_id": "1234",
"customer_email": "jim@gmail.com",
}
PERSON
Когда есть неясность в том, насколько далеко простирается группа, механизмы регулярных выражений сначала отдают предпочтение самому длинному совпадению. Для любого имени файла \(.*\)
соответствует полному имени, а \.*.*
соответствует пустой строке.
Вам понадобятся два футляра :с удлинителем или без него. Также обратите внимание, что если имя файла начинается с .
, это не начало расширения.
Я не понимаю, почему вы хотите использовать expr
. Управление параметрами оболочки стало проще.
При преобразовании в верхний регистр обратите внимание, что реализация tr
в Linux не поддерживает локали, отличные от -ASCII. Он выполняет только манипуляции с байтами. Например, echo accentué | tr a-z A-Z
приводит к ACCENTUé
, а не к ACCENTUÉ
. Вместо этого используйте инструмент с поддержкой локали -, такой как awk. В bash вы можете использовать ${filename^^?}
, но это недоступно в sh. Убедитесь, что ваш сценарий работает в правильной локали для кодировки имен файлов.
Я предполагаю, что имя файла не содержит части каталога. Если это так, сначала отделите его.
case $filename in
?*.*) # There is an extension
base="${filename%.*}"; ext=".${filename##*.}";;
*) # No extension
base="$filename"; ext="";;
esac
upcased_base="$(printf %s. %base | awk '$0 = toupper($0)')"
upcased="${upcased_base%.}$ext"
Конечный .
в %s.
, который затем удаляется из $upcased_base
, гарантирует, что сценарий правильно обрабатывает имена файлов с новой строкой непосредственно перед расширением. Без этого подстановка команды удалит завершающие символы новой строки. Вам это не нужно, если вы уже убедились, что ваши имена файлов не содержат символов новой строки.
Вот полностью основанное наawk
-решение, где вы должны поместить следующую строку в свой сценарий оболочки:
uppercasename="$(echo "$filename" | awk 'BEGIN{FS=OFS="."} NF==1{$1=toupper($1)} {for (i=1;i<NF;i++) $i=toupper($i)} 1')"
Это будет использовать .
в качестве разделителя полей для ввода и вывода и, если найдено только одно поле, преобразовать его в верхний регистр, а во всех других случаях преобразовать все поля, кроме последних, в верхний регистр.. Затем он печатает результат (это значение 1
, которое является сокращенной записью для{print}
).
Если вы используете bash
, вы можете избавиться от канала и указать его как
uppercasename="$(awk 'BEGIN{FS=OFS="."} NF==1{$1=toupper($1)} {for (i=1;i<NF;i++) $i=toupper($i)} 1' <<< "$filename")"
с помощью строки -.
Обратите внимание, что это разработано таким образом, что в пограничном случае имени файла, оканчивающегося на .
, как в myfile.this.txt.
, он будет рассматривать это как «пустой, но присутствующий суффикс» и преобразовывать его в MYFILE.THIS.TXT.
. Кроме того, если имя файла начинается с .
и не имеет другого расширения (, как в .myfile
), оно будет сохранено в нижнем регистре.
Если используется оболочка bash
, используется только расширение параметров bash:
file="aaa.bbb.dat"
name=${file%.*} # delete everything after last dot
ext=${file##*.} # delete everything up to last dot
upcase=${name^^*}.$ext # uppercase everything
echo "$upcase"
AAA.BBB.dat
Пробуем более сложный случай:
file="déjà vu. dat "
name=${file%.*} # delete everything after last dot
ext=${file##*.} # delete everything up to last dot
upcase=${name^^*}.$ext # uppercase everything
echo ":$upcase:"
Дает:
:DÉJÀ VU. dat :
Так: