Объединение двух переменных приводит их в действие в Windows

Я пытаюсь написать что-то для Bash в Windows System for Linux, которая преобразует ~ в ваш каталог пользователя Windows при передаче через функцию winpath . Пока что я могу получить каталог Windows и преобразовать его в путь Unix, и я также смогу найти часть после /home/[username]/ которая будет выводиться через ~ . Там, где я нахожусь в беде, это объединение этих двух.

У меня есть две переменные:

 $target_path=/home/jacob/Repositories $user_path=/mnt/c/Users/Jacob 

(На самом деле я извлекаю их программно, но я не думаю, что это имеет значение.)

Затем я /home/jacob из $target_path , оставляя его как just /Repositories .

Цель состоит в том, чтобы комбинировать $user_path с измененным $target_path , поэтому он выводится как:

 /mnt/c/Users/Jacob/Repositories 

Для этого я просто делаю:

 target_path=$user_path$target_path 

Но то, что происходит, по какой-то причине, выводится как:

 /RepositoriesJacob 

Это не имеет никакого смысла, потому что когда я $user_path на свой собственный, это правильно, и когда я $target_path на свой собственный, это тоже правильно. Таким образом, это что-то в сочетании этих двух, это испортить его.

Соответствующие строки составляют 8-20 в этом контексте (полный код, вставленный ниже).

 winpath() { # get the Windows user path user_path=$(/mnt/c/Windows/System32/cmd.exe /C echo %HOMEDRIVE%%HOMEPATH%) # expand the specified path target_path=$(readlink -f $1) # change ~ to $user_path (WIP) if grep -q "^/home/" <<< $target_path; then # convert Windows-style user path to Unix-style (ie from C:\Users\[username] to /mnt/c/Users/[username]) temp_user_path=$(echo "$user_path" | sed -e 's|\\|/|g' -e 's|^\([A-Za-z]\)\:/\(.*\)|/mnt/\L\1\E/\2|') # remove /home/[username]/ from $target_path target_path=$(echo "$target_path" | sed -e 's|^/home/\(.*\)/\(.*\)|/\2|') # output $temp_user_path for debugging echo $temp_user_path # correctly outputs # output $target_path for debugging echo $target_path # correctly outputs # combine the variables echo $temp_user_path$target_path # DOES NOT correctly output (?) fi # check if a Windows path is getting parsed if grep -q "^/mnt/[az]/" <<< $target_path; then # swap /mnt/[az]/ with [AZ]:/ and / with \ echo $(echo "$target_path" | sed -e 's|^\(/mnt/\([az]\)/\)\(.*\)|\U\2:\\\E\3|' -e 's|/|\\|g') else # return the user's home directory if a Unix path was parsed echo $user_path fi } 

EDIT: Хорошо, так что это странно … Попытка сделать это на Mac, все отлично. Может быть, это ошибка с WSL?

EDIT 2: после дальнейшего тестирования, похоже, что это связано с объединением двух выходов sed . Если я набираю строки как переменные и стараюсь их комбинировать, он работает нормально. Хм.

2 Solutions collect form web for “Объединение двух переменных приводит их в действие в Windows”

Да, дополнительное возвращение каретки – ваша проблема.

Подстановка процесса удаляет окончательную новую строку (поток строк) из результата процесса, но в случае, когда cmd.exe выводит пару CR-LF, возврат каретки остается в конце пути user_path . Когда печатается, CR заставляет выход возвращаться к началу строки при печати. Repositories имеют ту же длину, что и /mnt/c/Users поэтому следующая косая черта выравнивается в несколько логическом месте (вместо этого, если смотреть на любое слово было сломано).

Вы можете удалить ${user_path%$'\r'} CR внутри Bash с помощью ${user_path%$'\r'} . ( ${var%pattern} удаляет суффикс, соответствующий шаблону из переменной)

Кроме того, я думаю, что ваш второй sed ( 's|^/home/\(.*\)/\(.*\)|/\2|' ) слишком ревлив, первый .* Соответствует самой длинной строке может, так /home/user/foo/bar превратится в просто /bar вместо /foo/bar . Вы также можете сделать это с помощью расширений параметров: ${target_path#/home/*/} . С одним # он удаляет кратчайший соответствующий префикс.

Благодаря помощи @steeldriver, я смог понять это! Как ни странно, это была проблема с окончанием строк Windows, хотя CMD выводила только одну строку. Решение заключалось в том, чтобы преобразовать вывод CMD в стиль Unix, и это решило проблему! Вот мой последний код:

 winpath() { # get the Windows user path, convert to Unix line endings user_path=$(echo "$(/mnt/c/Windows/System32/cmd.exe /C echo %HOMEDRIVE%%HOMEPATH%)" | tr -d "\r") # expand the specified path target_path=$(readlink -f $1) # change ~ to $user_path if grep -q "^/home/" <<< $target_path; then temp_user_path=$(echo "$user_path" | sed -e 's|\\|/|g' -e 's|^\([A-Za-z]\)\:/\(.*\)|/mnt/\L\1\E/\2|' -e 's|^M$||') # if there was something after ~, add it to the end of the $user_path if grep -q "^/home/\(.*\)/\(.*\)" <<< $target_path; then target_path=$temp_user_path$(echo "$target_path" | sed -e 's|^/home/*/\(.*\)|/\2|') # if there was nothing after ~, $target_path is $user_path else target_path=$temp_user_path fi fi # check if a Windows path is getting parsed if grep -q "^/mnt/[az]" <<< $target_path; then # swap /mnt/[az] with [AZ]: and / with \ echo $(echo "$target_path" | sed -e 's|^\(/mnt/\([az]\)\)\(.*\)|\U\2:\E\3|' -e 's|/|\\|g') else # return the user's home directory if a Unix path was parsed echo $user_path fi } 
  • Файловая система, совместимая со всеми ОС?
  • Как сделать резервную копию данных моей системы Linux, если я хочу получить ее в других операционных системах?
  • Предоставление пользователю возможности читать только части файловой системы NTFS
  • Почему имена файлов выглядят «нормальными» в Linux, но не удаленно в Windows?
  • Избегайте проблем с Fedora и Windows путем установки на отдельные жесткие диски?
  • Как звуковая проблема Linux может повлиять на Windows в конфигурации с двойной загрузкой?
  • Печать на клиент ubuntu через сеть, используя php, который находится в веб-сервере Windows 7
  • Необходимо загрузить Windows 7 из командной строки Grub rescue
  • Инструкции Samba работают на CentOS 6.5, но не CentOS 6.3 - разрешения в Windows разные
  • Перемещение программного обеспечения RAID 1 в Linux
  • Как получить Windows на меню grub? Использование двух жестких дисков; Сначала загрузочный загрузчик Windows
  • Linux и Unix - лучшая ОС в мире.