Седан не соблюдает символ $ address, когда я пытаюсь сопоставить только последнее вхождение из скрипта - PullRequest
0 голосов
/ 10 октября 2019

** ПРИМЕЧАНИЕ: я также задавал этот вопрос по обмену стека, потому что у меня возникли проблемы при редактировании этого поста. К счастью, я получил ответ там:

https://unix.stackexchange.com/questions/546208/sed-in-not-honoring-the-address-char-when-i-try-to-only-match-last-occurrence?noredirect=1#comment1013405_546208

^^^ СМОТРИТЕ ССЫЛКУ НА РЕШЕНИЕ, ЧТО Я НАШЕЛ, ЧТО РАБОТАЛ ДЛЯ МЕНЯ ^^^

Я создалпростой скрипт, который я хочу использовать для переименования файлов на основе шаблона.

Скрипт использует find и sed для своей работы,

В основном все работает, кроме случаев, когда я использую $ toсказать sed, чтобы он совпадал только с последним вхождением, он не может ничего сопоставить.

Если я удаляю $, все совпадения совпадают, так что это работает, но я специально хочу нацелить только на последнее вхождение. Пример: sed "s / $ {search} / $ {replace} / g" # Находит совпадения sed "s / $ {search} $ / $ {replace} / g" # Не находит совпадений

IУпрощенный код ниже, функция searchReplaceLastMatchOnly () демонстрирует, что я пытаюсь сделать с sed, который не работает.

Функция searchReplace () показывает, как шаблон sed находит совпадения, если адрес $ не используется.

Мой тестовый каталог выглядит следующим образом: ./bar ./bar/baz ./bar / foobar.txt ./bar/baz/foobar.txt

# Search and replace using command: sed "s/${search}/${replace}/g")"
# This works, but is not what i want, i just need last occurence.
function searchReplace() {
    # spaces are set as defaults
    target=${1:- }
    search=${2:- }
    replace=${3:- }
    result="$(printf "%s" "$target" | sed "s/${search}/${replace}/g")"
    printf "%s" "$result"
}

# Search and replace using command: sed "s/${search}$/${replace}/g")"
# This is what I have read should work, using $ should only match
# last occurence, this is what I want but it does not work.
function searchReplaceLastMatchOnly() {
    # spaces are set as defaults
    target=${1:- }
    search=${2:- }
    replace=${3:- }
    ### sed NOT WORKING WITH $ ###
    result="$(printf "%s" "$target" | sed "s/${search}$/${replace}/g")"
    printf "%s" "$result"
}

# demo
search="bar"
replace="Bar"
dirPath="."
pattern="*.txt"
printf "\n"
find "$dirPath" -type f -name "$pattern" | while IFS= read -r original; do
    modified="$(searchReplaceLastMatchOnly "$original" "$search" "$replace")"
    printf "\nRenaming %s to %s\n" "$original" "$modified"
    #mv "$original" "$modified"
done
printf "\n"

# Currently this has following results:
#
# Renaming ./bar/baz/foobar.txt to ./bar/baz/foobar.txt
#
# Renaming ./bar/foobar.txt to ./bar/foobar.txt
#

printf "\n"
find "$dirPath" -type f -name "$pattern" | while IFS= read -r original; do
    modified="$(searchReplace "$original" "$search" "$replace")"
    printf "\nRenaming %s to %s\n" "$original" "$modified"
    #mv "$original" "$modified"
done
printf "\n"

# Currently this has following results:
#
# Renaming ./bar/baz/foobar.txt to ./Bar/baz/fooBar.txt
#
# Renaming ./bar/foobar.txt to ./Bar/fooBar.txt

1 Ответ

0 голосов
/ 10 октября 2019

Не ответ, но чтобы дать вам представление о (GNU) sed флажках.

g флажок для глобального, замените все совпадения.

$ echo barbarbar.etc | sed 's/bar/foo/g'
foofoofoo.etc

$ echo barbarbar.etc | sed 's/bar/foo/'
foobarbar.etc        

$ echo barbarbar.etc | sed 's/bar/foo/1'
foobarbar.etc

$ echo barbarbar.etc | sed 's/bar/foo/2'
barfoobar.etc

$ echo barbarbar.etc | sed 's/bar/foo/3'
barbarfoo.etc

$ echo barbarbar.etc | sed -E 's/bar(.etc)$/foo\1/'
barbarfoo.etc

$ здесь якорь для конца строки, не требуется для указанного выше ввода, но для другого ввода он будет соответствовать только экземпляру в конце строки.

$ echo barbarbar.etc bar.etc| sed -E 's/bar(.etc)$/foo\1/'
barbarbar.etc foo.etc
...