Преобразование первой буквы в нижний регистр с помощью sed - PullRequest
0 голосов
/ 10 сентября 2018

Я использую образ Docker Alpine, на котором установлен bash.

bash --version
GNU bash, version 4.3.48(1)-release (x86_64-alpine-linux-musl)

В следующей команде я пытаюсь преобразовать первую букву месяца в нижний регистр, но она не работает:

find ../ -type f -name "*.md" \
        -exec bash -c '
            f=${1#./}
            gzip -9 "$f"
            mv "$f".gz "$f"
            aws s3 cp "$f" s3://bucket_name/ --metadata time=$(date +%d-%b-%Y.%H%M | sed '\''s#\([A-Z]\)#\L\1#'\'') ' _ {} \;

Атрибут даты, который он назначает файлам:

"Metadata": {
    "timestamp": "10-LSep-2018.1054"
}

\L не работает в этом случае. Ожидаемая дата должна была быть "10-sep-2018.1054"

Как мне заставить его работать с версией bash, представленной в образе Docker?

Ответы [ 5 ]

0 голосов
/ 11 сентября 2018

Это может сработать для вас (GNU sed):

sed 's/$/:JjFfMmAaSsOoNnDd/;s/\([JFMASOND]\)\(.*\):.*\1\(.\).*/\3\2/' file

Это заменяет заглавную букву J, F, M, A, S, O, N или D. дополнением к нижнему регистру.

0 голосов
/ 10 сентября 2018

Как выяснилось, OP имеет доступ только к минимальной версии sed, которая не распознает команду замены \ L, и для его случая использования допустимо использование заглавных букв ВСЕ в выводе.

Самый простой способ добиться этого - с помощью команды

tr [:upper:] [:lower:]

, хотя для этого, безусловно, существуют и другие жизнеспособные варианты, такие как решение "pure bash", предложенное @PesaThe, или использование sed "y."команда transform, как это было предложено Андреа Джаммарки, если она доступна (хотя я бы сказал, что два других варианта предпочтительнее, поскольку в них применяются инструменты, более специализированные для выполнения задачи).

Если ТОЛЬКО первая заглавная буква выходных данных можетбыть преобразованным и команда замены sed \ L недоступна, я бы предложил обратиться к более способному языку сценариев или программирования, где задача должна быть тривиальной для решения.Это должно быть возможно и в «чистом ключе», но подходы, которые я могу придумать вне очереди, кажутся непропорционально сложными.

Для иллюстрации, вот минимальная программа на С, которая соответствует задаче, даннойсоответствующая ситуация кодирования:

#include <stdio.h>
main() {
    int c;
    while ((c = getchar()) != EOF) {
        if (c >= 'A' && c <= 'Z') {
            putchar(c + 'a' - 'A');
            break;
        }
        putchar(c);
    }
    while ((c = getchar()) != EOF) putchar(c);
}
0 голосов
/ 10 сентября 2018

Есть несколько вариантов возможного ответа в этой другой теме , но следующий, который, кажется, удовлетворяет ваши потребности, и его также легче всего читать, следующий:

sed 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/'

Это должно работать почти везде, включая macOS.

0 голосов
/ 10 сентября 2018

Это GNU sed должно сделать:

$ date +'%d-%b-%Y.%H%M' | sed 's/-./\L&/'
10-sep-2018.1332

Чтобы избежать этого в bash -c '...':

bash -c '... time="$(date +"%d-%b-%Y.%H%M" | sed "s/-./\L&/")" ...'

Если у вас нет GNU sed (необходимо для расширения \L), просто сохраните дату в переменной и используйте расширение параметра :

$ d=$(date +'%d-%b-%Y.%H%M')
$ echo "${d,,}"
10-sep-2018.1337
0 голосов
/ 10 сентября 2018

Вопрос можно было бы упростить, показав только затронутую часть:

date +%d-%b-%Y.%H%M | sed '\''s#\([A-Z]\)#L\1#'\''

Прежде всего, позвольте мне "почистить" это:

date +%d-%b-%Y.%H%M | sed 's#\([A-Z]\)#L\1#'

То, что я вижу здесь, это то, что вы используете L как буквенную букву, а не как команду. Вы должны избежать этого (\ L), как это:

date +%d-%b-%Y.%H%M | sed 's#\([A-Z]\)#\L\1#'

Вы можете проверить это, выполнив:

:~# docker container run --rm alpine /bin/sh
/ # date +%d-%b-%Y.%H%M | sed 's#\([A-Z]\)#\L\1#'
10-LSep-2018.1510
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...