Удалите последний знак из строки

Вашим вопросом является на самом деле Bash FAQ № 89: просто добавьте предотвратить ffmpeg от чтения его стандартного входа.


Я брал на себя смелость согласовывания Вашего сценария для Вас, потому что это содержит много потенциальных ошибок. Несколько важных моментов:

  • Имена файлов хитры для обработки, потому что большинство файловых систем позволяет им содержать все виды непечатных символов, которые нормальные люди рассматривали бы как мусор. Создание упрощения предположений как "имена файлов содержит только 'нормальные' символы", имеет тенденцию заканчиваться хрупкие сценарии оболочки, которые, кажется, работают над "нормальными" именами файлов и затем повреждают день, они сталкиваются с особенно противным именем файла, которое не следует за предположениями сценария. С другой стороны, правильно обрабатывающие имена файлов могут быть таким беспокойством, что можно найти его не стоящим усилия, если шанс обнаружения со странным именем файла, как ожидают, будет близким нулем (т.е. Вы только используете сценарий на своих собственных файлах, и Вы даете Вашим собственным файлам "простые" имена). Иногда возможно избежать этого решения в целом, не анализируя имена файлов вообще. К счастью, это возможно с find(1) -exec опция. Просто помещенный {} в аргументе -exec и Вы не должны волноваться о парсинге find вывод.

  • Используя sed или другие внешние процессы, чтобы сделать операции простой строки как разделение расширений и префиксов неэффективны. Вместо этого используйте расширения параметра, которые являются частью оболочки (никакой внешний процесс не означает, что это будет быстрее). Некоторые полезные статьи о предмете упоминаются ниже:

  • Использовать $( ), и не используйте `` больше: Bash FAQ 82.

  • Избегайте использования ПРОПИСНЫХ имен переменной. То пространство имен обычно резервируется оболочкой для особых целей (как PATH), так использование его для Ваших собственных переменных является плохой идеей.

И теперь, без дальнейшей суматохи, вот очищенный сценарий для Вас:

#!/bin/sh

logfile=encodemp4ize.log
echo "Started at $(date)." > "$logfile"
rsync -avz --exclude '*.flv' flvs/ mp4s/

find flvs/ -type f -name '*.flv' -exec sh -c '
for flvsfile; do
    file=${flvsfile#flvs/}
    < /dev/null ffmpeg -i "$flvsfile" -vcodec libx264 -vprofile high \
        -preset slow -b:v 500k -maxrate 500k -bufsize 1000k \
        -threads 0 -acodec libfaac -ab 128k \
        "mp4s/${file%flv}"mp4
    printf %s\\n "$flvsfile MP4 done." >> "$logfile"
done
' _ {} +

Примечание: Я использовал POSIX sh потому что Вы не использовали или нуждаетесь в любом bash- определенные функции в Вашем оригинале.

56
18.09.2013, 15:20
11 ответов
sed 's/.$//'

Удалить последний знак.

Но в этом конкретном случае, Вы могли также сделать:

df -P | awk 'NR > 1 {print $5+0}'

С арифметическим выражением ($5+0) мы вызываем awk для интерпретации 5-го поля как числа и чего-либо после, число будет проигнорировано.

Отметьте тот GNU df (Ваш -h уже расширение GNU, хотя не нужный здесь) может также быть сказан только произвести процент использования диска:

df --output=pcent | tail -n +2 | tr -cd '0-9\n'

(хвост пропускает заголовки, и TR удаляет все кроме цифр и разделителей строки).

На Linux см. также:

findmnt -no USE%
86
27.01.2020, 19:33

С sed, это довольно легко:

$ cat file
Use%
22%
1%
1%
59%
51%
63%
5%
$ sed 's/.$//' file
Use
22
1
1
59
51
63
5

Синтаксис s(ubstitute)/search/replacestring/. . указывает на любой символ, и $ конец строки. Так .$ удалит последний знак только.

В этом случае Ваша полная команда посмотрела бы:

df -h | awk '{ print $5}' | sed 's/.$//'
21
27.01.2020, 19:33
  • 1
    Канал к sed избыточно: в этом можно выполнить awk: df -h | awk '{gsub(/%/,""); print $5}' –  jasonwryan 15.07.2013, 09:33
  • 2
    @jasonwryan Затем мне нравится решение Stephane лучше. –  Bernhard 15.07.2013, 09:35

В awk Вы могли сделать один из

awk '{sub(/%$/,"",$5); print $5}'
awk '{print substr($5, 1, length($5)-1)}'
8
27.01.2020, 19:33

другой подход:

mapfile -t list < <(df -h)
printf '%s\n' "${list[@]%?}"

Превратите его в функцию:

remove_last() {
  local char=${1:-?}; shift
  mapfile -t list < <("$@")
  printf '%s\n' "${list[@]%$char}"
}

Затем назовите его как это:

remove_last '%' df -h

mapfile bash4 функция.

Выгода здесь - то, что необходимо предоставить символ для удаления; если Вы хотите, чтобы это просто было независимо от того, что последний знак, оказывается, затем, необходимо передать '?' или ''. кавычки требуются.

2
27.01.2020, 19:33

У меня есть два решения:

  1. cut: echo "somestring1" | rev | cut -c 2- | rev

    Здесь вы реверсируете строку, вырезаете строку из 2-го символа и снова реверсируете.

  2. sed : echo "somestring1" | sed 's/.$//'

    Здесь вы будете искать регулярное выражение . $, что означает любые символы, за которыми следует последний символ, и заменить его на ноль // (между двумя косая черта)

15
27.01.2020, 19:33
$ df -h | awk '{print $5}' | cut -d '%' -f1 
1
27.01.2020, 19:33

Попробуйте следующее:

df -h | awk  '{ print $5 }' | sed "s/%//"

Обычное использование: (т.е.)

VALUE=987654321
echo X123456789X | sed "s/123456789/${VALUE}/"

Ответ должен быть: X987654321X

1
27.01.2020, 19:33
df -h | awk 'NR > 1{ print $5 }' | cut -d "%" -f1
4
27.01.2020, 19:33
sed -ie '$d' filename

here -i is to write changes
      e means expression
      $ means last line
      d means delete

Note:Without -e option $ wont work

Дополнительно:Чтобы удалить 1-ю и последнюю строку, используйте sed -ie '1d;$d'имя файла

0
27.01.2020, 19:33
echo "123" | perl -ple 'chop'
12
3
27.01.2020, 19:33

Знаете ли вы, что headи tailмогут работать посимвольно, а не построчно?

$ printf "I don't like periods." | head -c-1
I don't like periods

(Кстати, printfиспользуется здесь для предотвращения печати символа «новой строки» в конце строки. Если в вашем выводе есть символ новой строки, и вы хотите удалить его, а также последний символ пробела, отличный от -, используйтеhead -c-2).

Это в основном то же самое, что и решение "Гуру" с использованием cut, но без причудливых revтуда и обратно, которые им нужно использовать, потому что cutне имеет синтаксиса для "последних n вещей".

Чтобы перебрать поток строк и удалить последний символ каждой, можно сделать что-то вроде этого:

some-command | while read line; do echo $(head -c-2 <<<"$line"); done
2
15.12.2020, 17:14

Теги

Похожие вопросы