sed заменяет позиционное совпадение неизвестной строки на разделенный пользователем разделитель - PullRequest
1 голос
/ 25 марта 2019

Хотите переименовать (известную) 3-ю папку в (неизвестном) пути к файлу из строки, когда она расположена на 3-м уровне, когда разделитель равен /

Нужен однострочно для sed. Потому что позже я хочу использовать его для tar --transform = EXPRESSION

string="/db/foo/db/bar/db/folder"
echo -e "$string" | sed 's,db,databases,'

sed заменяет "db" только на 3-м уровне

ожидаемый результат

/db/foo/databases/bar/db/folder

Ответы [ 3 ]

1 голос
/ 25 марта 2019

Если awk также является опцией для этой задачи:

$ awk 'BEGIN{FS=OFS="/"} $4=="db"{$4="database"} 1' <<<'/db/foo/db/bar/db/folder'
/db/foo/database/bar/db/folder
  • FS = OFS = "/" назначить / для разделителей полей ввода и вывода,
  • $4 == "db" { $4 = "database }", если четвертое поле db, сделать его database,
  • 1 распечатать запись.
1 голос
/ 25 марта 2019

Вы можете использовать группу захвата для захвата /db/foo/, а затем сопоставить db.Затем используйте первую группу в замене, используя \1:

string="/db/foo/db/bar/db/folder"
echo -e "$string" | sed 's,^\(/[^/]*/[^/]*/\)db,\1databases,'

О шаблоне

  • ^ Начало строки
  • \( Начать захват группы
    • /[^/]*/[^/]*/ Сопоставить первые 2 части, используя отрицательный класс символов
  • \) Закрыть группу захвата
  • dbСовпадение буквально

Это даст вам

/db/foo/databases/bar/db/folder
0 голосов
/ 25 марта 2019

Вот простой способ сделать это путем установки IFS=/ без вызова какой-либо внешней утилиты:

string="/db/foo/db/bar/db/folder"
string=$(IFS=/; read -a arr <<< "$string"; arr[3]='databases'; echo "${arr[*]}")
echo "$string"

/db/foo/databases/bar/db/folder
...