Найти и заменить с помощью регулярного выражения на sed [closed]

Ha demostrado múltiples patrones anti -en su código que podrían mejorarse. Consulte Por qué no debería analizar la salida de ls (1). No es necesario analizar la salida del comando lsy evitar el uso de varias líneas de shell pipe -con el comando try find.

Se recomienda mejor utilizar las opciones globales proporcionadas por el shell nativo, que en su caso debería ser el shell bash.

El fragmento de código $(ls *.mp3 | tr '\n' '|')bien podría escribirse en bashcon las opciones que proporciona para la acumulación de archivos como

shopt -s nullglob
mp3FileList=(*.mp3)

Esta opción de shell extendida está habilitada para garantizar que se omita el resultado global vacío en lugar de procesarse cuando se llena la matriz. Debe cden la carpeta y hacer lo siguiente. Tenga en cuenta el final |después de la matriz, ya que originalmente también lo tenía en la lista. Quítelo si no es necesario.

fileString=$( IFS='|'; echo "${mp3FileList[*]}|" )

Ahora, la variable anterior contendría la lista de archivos en un formato separado |con un |al final que luego se puede pasar a su comando ffmpegcomo

ffmpeg -i "concat:${fileString}" -acodec opus test.opus

Con respecto a su segundo requisito para pasar múltiples opciones al script. Podría extender este script para hacer

audioConcat() {
    (( "$#" < 3 )) && { printf 'insufficient arguments supplied' >&2; exit 1 ; }
    cd "$1" || { printf 'unable to navigate to target\n' >&2; exit 2 ; }

    shopt -q nullglob; nullglob_set=$?
    ((nullglob_set)) && shopt -s nullglob

    local fileList
    local fileString

    fileList=(*."${2}")

    if (( ${#fileList[@]} )); then
        fileString=$( IFS='|'; echo "${fileList[*]}" )
        ffmpeg -i "concat:${fileString}" -acodec "$3" "$1.$3"  
    else
        printf 'unable to find files of extension %s\n' "$2" >&2
        exit 3 
    fi

    ((nullglob_set)) && shopt -u nullglob      
}

Recuerde cuando llame a la función, pase sus argumentos como

audioConcat '/path/to/mp3files/' 'mp3' 'opus'

Le recomendaría encarecidamente comentar la línea ffmpegen la función anterior y ver si las variables se crean según sea necesario antes de llamar al comando real.Confirme también si necesita el final |en su lista de archivos.

Resumen rápido de las construcciones utilizadas en la función

  1. La opción nullglobconfigurada durante la expansión del nombre de la ruta evitaría expandir un globo vacío, es decir, cuando no se encuentran archivos .mp3, la matriz estaría vacía durante la expansión en lugar de un globo sin expandir
  2. $(IFS='|'; echo "${mp3FileList[*]})es un buen truco para producir para imprimir la salida en |formato separado. Estamos modificando el IFSen un shell secundario -(el Separador de campo de entrada )para que no se modifique globalmente. La expansión de la matriz con [*]concatenaría la cadena con el conjunto de valores IFS.

Algunos misceláneos. notas para considerar :-El uso de exiten la función en realidad saldría del shell actual en el que está ejecutando la función. Es posible que no se recomiende cuando se usa desde la línea de comando -y es más adecuado cuando se ejecuta desde un script con un intérprete adecuado que -bang set, en cuyo caso saldría del shell sub -iniciado para ejecutar el script. Si planea usar desde la línea de comando con más frecuencia, reemplace las llamadas exitcon return.

-1
01.05.2017, 13:00
2 ответа

Ваша команда sed немного запуталась.

sed -i '' "remote_paths/.*[\/]([^\"]*)/$BRANCH_NAME/g"

Прежде всего, не используйте sed с -i, если вы все еще пытаетесь заставить что-то работать. Это просто рецепт уничтожения важных файлов.

Во-вторых, r в remote_path — это команда sed, которая читает файл. Я почти уверен, что он ищет файл с именем emote_paths/.*[\/]([^\"]*)/$BRANCH_NAME/g или хотя бы emote_paths.В любом случае он не выйдет с ошибкой, если файл не существует.

Похоже, вы хотели что-то вроде

s#\(remote_path.*/home/myname/public_html/\)\([A-Z0-9-]*\)#\1$BRANCH_NAME#g

Команда становится

sed "s#\(remote_path.*/home/myname/public_html/\)\([A-Z0-9-]*\)#\1$BRANCH_NAME#g" \
  "$WORKING_DIR/sftp-config.json" >"$WORKING_DIR/sftp-config.json.new"

Или, если имя ветки находится в конце строки после последнего / и строки remote_path однозначно находит эту строку:

sed "/remote_path/s#/[^/]*\$#$BRANCH_NAME#" \
  "$WORKING_DIR/sftp-config.json" >"$WORKING_DIR/sftp-config.json.new"

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

jq ".remote_path = (.remote_path | split(\"/\") | .[-1] = \"$BRANCH_NAME\" | join(\"/\"))" \
  input.json >output.json
2
29.04.2021, 00:01

(1) remote_path кажется адресом, фильтрующим строку по этому шаблону? Затем окружите его косой чертой: /remote_path/

(2) Кажется, вы создаете выражение для всей строки, но хотите заменить только часть, отмеченную на (). Правильно? Но они используются совершенно по-разному (группировка или обратные ссылки), и вам нужно их экранировать \(\)или использовать опцию -E для расширенных регулярных выражений

(3 ) Найдите шаблон, который соответствует только заменяемому названию ветки в виде тире между прописными буквами и цифрами: [AZ]*-[0-9]*

Получаем

sed -i '' "/remote_path/s/[A-Z]*-[0-9]*)/$BRANCH_NAME/g" "$WORKING_DIR"/sftp-config.json

И попробуем без опция -i первая

0
29.04.2021, 00:01

Теги

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