2

У меня есть скрипт, который перечисляет кучу файлов, которые соответствуют определенным критериям. Он выводит только имена файлов, и есть куча текста, который не нужен.

Пример строки:

[gg]_Magi_-_13_[DB38165F].mkv

Что я хотел бы достичь в выводе:

[gg]_Magi_-_13

Мне удалось заменить подчеркивание, но мне не повезло в успешной обрезке [CRC32] .mkv. Также я ограничиваю количество символов и помещаю многоточие в конец, если они выходят за пределы 28 символов, но даже если оно не выходит за пределы 28 символов, оно все равно добавляет многоточие на конец.
Код для этого:

print substr( $0, 0, 28 )"[…]"}

Помощь по любой из этих проблем будет высоко ценится.

5 ответов5

2

Я думаю, что это самое короткое решение, которое отвечает всем критериям

awk '{
    if (match($0, "^(.*)_[^_]+$", a)) {
        print substr(a[1], 1, 27) (length(a[1]) > 27 ? "..." : "")
    }
}'
1

Хотя у awk , sed и company есть свои достоинства, они не нужны для этого. Вы можете легко достичь всего, что просили, используя только операции строки bash и сопоставление с образцом. Предполагая, что вы присвоили свое имя файла $name:

name="${name%_\[*\].*}"

будет отрезать тип файла и заключенный в скобки CRC из $name . Если вам нужно убедиться на 100%, что вы отключили только CRC, вы можете использовать расширенное регулярное выражение вместо вышеперечисленного:

[[ $name =~ (.*)_\[[[:xdigit:]]{8}\]\..*$ ]] && name="${BASH_REMATCH[1]}"

Усечение имен длиннее 28 символов достигается:

(( ${#name} > 28 )) && name="${name::27}…"

- две строки общего количества bash (не считая логики, цикла или чего-то другого, чтобы получить имена ваших файлов в var и, конечно же, выходной код), без внешних факторов. Основным преимуществом является то, что код работает быстро, поскольку оболочке никогда не требуется запускать какие-либо внешние двоичные файлы.

1
sed -e 's/_\[.*\.mkv//' -e 's/^\(.\{28\}\).*/\1.../' file.txt

Первый бит удаляет _[blah].mkv , а второй бит печатает первые 28 символов и помещает ... в конец - но если строка меньше 28 символов, он печатает только удаленное имя файла, без добавления эллипсов.

Если расширение файла не всегда будет * .mkv, вы можете использовать это (в sed символ $ означает «до конца строки»):

sed -e 's/_\[.*$//' -e 's/^\(.\{28\}\).*/\1.../' file.txt
0

Не самое чистое решение, но вы могли бы сделать это:

 echo "[gg]_Magi_-_13_[DB38165F].mkv" | awk -F '_' '{print $1"_"$2"_"$3"_"$4}'

РЕДАКТИРОВАТЬ: Мех, поцарапать этот ответ. Это не даст вам элипсис.

0

Попробуйте эту функцию bash (предупреждение: не проверено):

function convert_filename {
    # Regex guide:
    #   ^(.*)_?                everything since the beginning of the string,
    #                          optionally followed by an underscore
    #   \[[a-fA-F0-9]{8}\]    8 hexadecimal characters, surrounded by []
    #   \.(.\w+)$              filename extension at the end of the string
    local r="$(echo "$1" | sed -r 's/^(.*)_?\[[a-fA-F0-9]{8}\]\.(.\w+)$/\1/')"
    if (( ${#r} < 28 )); then
        # Outputs $r
        echo "$r"
    else
        # Outputs the first 27 characters from $r followed by an ellipsis
        echo "${r::27}…"
    fi
}

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .