Как мне разделить список путей без кавычек со встроенными пробелами на отдельные пути?

#string #bash #shell #divide

#строка #bash #оболочка #разделить

Вопрос:

Я не силен в написании сценариев оболочки bash в Ubuntu, поэтому мне нужна ваша помощь.

Проблема в том…

Мы используем Perforce для SCM.

Я пытаюсь получить каталоги из //Development/ ветвей.

До этого времени все было хорошо.

Но теперь я больше не могу разделять ветви пробелами из-за таких ветвей, как следующие (обратите внимание на встроенный пробел):

//Development/graphic/release/Unity Provider

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

// Разработка / графика / релиз / Единство
Поставщик

Как я могу это исправить?

Пожалуйста, помогите мне. Спасибо.

Ниже приведен пример однострочной строки:

 //Development/graphic/release/CM //Development/graphic/release/GManager //Development/graphic/release/Notification //Development/graphic/release/Core //Development/graphic/release/Provider //Development/graphic/release/WH //Development/graphic/release/Accessory //Development/graphic/release/Unity Provider //Development/graphic/release/tipManager
  

И я хочу получить результирующую строку, как показано ниже (имя каждой ветви в отдельной строке):

 //Development/graphic/release/CM 
//Development/graphic/release/GManager 
//Development/graphic/release/Notification 
//Development/graphic/release/Core 
//Development/graphic/release/Provider 
//Development/graphic/release/WH 
//Development/graphic/release/Accessory 
//Development/graphic/release/Unity Provider 
//Development/graphic/release/tipManager
  

Я также хочу сохранить результаты в переменной списка.

Например, list[0] должен содержать . //Development/graphic/release/CM

Комментарии:

1. каков ваш ожидаемый результат?

2. Как вы определяете каталоги? Вы не можете переименовать каталог в Unity-Provider , чтобы избежать мучений с пробелами в имени пути?

Ответ №1:

Я предполагаю, что:

  • вы хотите разделить входную строку на отдельные пути на основе подстрок, начинающихся с //[Development/] , либо в начале строки, либо, если внутри, перед одним пробелом.
  • независимо от того, содержат ли строки между //[Development/] экземплярами пробелы или нет.
 str='//Development/graphic/release/CM //Development/graphic/release/GManager //Development/graphic/release/Notification //Development/graphic/release/Core //Development/graphic/release/Provider //Development/graphic/release/WH //Development/graphic/release/Accessory //Development/graphic/release/Unity Provider //Development/graphic/release/tipManager'    

echo "$str" | sed 's# (//)#'$'n''1#g'
  

Приведенное выше должно работать с любой POSIX-совместимой sed реализацией.

Чтобы записать выходные данные в переменной, используйте подстановку команд:

 result=$(echo "$str" | sed 's# (//)#'$'n''1#g')
  

Если затем вы хотите обработать результат построчно:

 while read -r path; do echo "$path"; done <<<"$result"
  

Объяснение sed команды:

  • # был — произвольно — выбран в качестве разделителя для sed команды ‘s s (подстановка строки), чтобы упростить сопоставление / символов (обычно / используется в качестве разделителя, что потребовало бы экранирования / экземпляров в регулярном выражении и заменяющей строке).
  •  (//) совпадает // , если перед ним стоит пробел, т.Е. Внутри строки.
  • '$'n'' эффективно вставляет новую строку ( n ) в строку замены, используя кавычки ANSI C (требуется для совместимости с OSX; в Linux просто n подойдет).
  • 1 вставляет 1-ю (и единственную) группу захвата из регулярного выражения, т.е, //
  • g гарантирует, что соответствие является глобальным, т. Е. Заменяются все подстроки, соответствующие регулярному выражению.

Результат:

 //Development/graphic/release/CM
//Development/graphic/release/GManager
//Development/graphic/release/Notification
//Development/graphic/release/Core
//Development/graphic/release/Provider
//Development/graphic/release/WH
//Development/graphic/release/Accessory
//Development/graphic/release/Unity Provider
//Development/graphic/release/tipManager
  

Комментарии:

1. Спасибо за вашу помощь, но я не могу использовать опцию -E в sed cmd. Я думаю, что эта ос redhat

2. @user3754723: Понятно. Я только что обновил свой ответ, чтобы сделать его совместимым с POSIX, что должно сработать для вас — дайте мне знать, если это не так.

3. Большое вам спасибо, и… У меня есть еще один вопрос …:) Как я могу сохранить его в переменной? список = echo "$str" | sed 's# (//)#'$'n''1#g' Это не работает, я хочу. Я хочу сохранить его в list.

4. @user3754723 Добро пожаловать; повторный захват выходных данных в переменной: см. Мое обновление.

5. Ну, мне все равно нужно получить тот же результат: ( for element in $result do echo $element done Извините, я не могу красиво прокомментировать, используя новую строку 🙁

Ответ №2:

Используйте переменную разделителя внутренних полей (IFS) для разрыва в новой строке вместо пробела.

Это хорошо объясняет: http://mindspill.net/computing/linux-notes/using-the-bash-ifs-variable-to-make-for-loops-split-with-non-whitespace-characters/

Пример, взятый по ссылке выше:

 #!/bin/bash
IFS=$','
vals='/mnt,/var/lib/vmware/Virtual Machines,/dev,/proc,/sys,/tmp,/usr/portage,/var/tmp'
for i in $vals; 
     do echo $i; 
done
unset IFS
  

Комментарии:

1. Повторная терминология: новые строки также являются формой пробела (пробела). Пример ввода OP представляет собой однострочную строку , поэтому разделение на новые строки не применяется.

Ответ №3:

Вы также можете попробовать эту команду awk,

 $ awk -v RS=" //" '{gsub (/^D/,"//D");}1' file
//Development/graphic/release/CM
//Development/graphic/release/GManager
//Development/graphic/release/Notification
//Development/graphic/release/Core
//Development/graphic/release/Provider
//Development/graphic/release/WH
//Development/graphic/release/Accessory
//Development/graphic/release/Unity Provider
//Development/graphic/release/tipManager 
  

Комментарии:

1. Нет, нет ~ я хочу сделать это, как показано ниже: // Разработка / графика / релиз / CM // Разработка / графика / релиз / GManager // Разработка / графика / релиз / Уведомление // Разработка / графика / релиз / Ядро // Разработка / графика / релиз / Поставщик // Разработка /графический / релиз / WH // Разработка / графический / релиз / Аксессуар // Разработка / графический / релиз / Поставщик единства // Разработка / графический / релиз / tipManager

2. опубликуйте приведенный выше комментарий в своем вопросе.