bash "пройти через" скрипт для сборки Android, проблема с пространством

485
codeScriber

У меня есть сборка Android, мне нужно настроить, вопрос, а не в stackoverflow, потому что моя проблема была с Bash. Я написал сценарий:

#!/bin/bash -xv params=$@ if [ "$#" -ge "2" ]; then params=$1 shift params="$params --custom-package com.some.package" while [ "$#" -gt "0" ]; do temp=$1 echo $1 | grep ' ' > /dev/null if [ "$?" -eq "0" ]; then temp=\"$1\" fi params="$params $temp" shift done  fi path=$(echo $0|xargs dirname) echo $params $path/aapt-orig $params 

Предполагается, что скрипт принимает параметры, которые он получил, добавляет параметр --custom-package com.some.package и сохраняет остальные параметры. Первый ($ 1) параметр - это действие, поэтому мне нужно сохранить его первым.

Проблема с пробелами в именах каталогов, например, «./my android dir /». если я просто передам параметр через: param = "$ param $ 1"; дерьмо; если в имени есть пробелы, это не работает, потому что новый параметр не экранирован (с помощью "), если я использую приведенный выше код, он все равно не работает, потому что по какой-то причине bash игнорирует символ" char "и по-прежнему учитывает пробел в середине как отдельный параметр! Вот результат выполнения: «./aapt action» / Users / bankleumi / some dir / «another_param»

'[' 0 -eq 0 ']' + temp='"/Users/bankleumi/some dir/"' + params='action --custom-package com.leumi.leumiwallet "/Users/bankleumi/some dir/"' + shift + '[' 1 -gt 0 ']' + temp=another_param + echo another_param + grep ' ' + '[' 1 -eq 0 ']' + params='action --custom-package com.leumi.leumiwallet "/Users/bankleumi/some dir/" another_param' + shift + '[' 0 -gt 0 ']' path=$(echo $0|xargs dirname) echo $0|xargs dirname ++ echo ./aapt ++ xargs dirname + path=. echo $params + echo action --custom-package com.leumi.leumiwallet '"/Users/bankleumi/some' 'dir/"' another_param action --custom-package com.leumi.leumiwallet "/Users/bankleumi/some dir/" another_param $path/aapt-orig $params + ./aapt-orig action --custom-package com.leumi.leumiwallet '"/Users/bankleumi/some' 'dir/"' another_param 

Как вы можете видеть в конце печати echo bash, рассматривайте строку "/ Users / bankleumi / some dir" как две строки, даже если в строку встроено \ "! Как я могу заставить bash оставить пространство в покое? (Я пытался играть с IFS, и это тоже не сработало ...)

1

2 ответа на вопрос

2
grawity

Не связывайтесь с повторными кавычками, это не сработает из-за того, что sh / bash использует разбиение слов по переменным - то есть они разделяют значение без предварительного рассмотрения кавычек в значении.

Вы можете обойти это, используя eval "$path/aapt-orig $params"...

Но у Bash есть массивы, используйте их вместо:

#!/usr/bin/env bash args=() args+=("$1"); shift args+=(--custom-package com.leumi.leumiwallet) for arg in "$@"; do args+=("$arg") done exec "$(dirname "$0")/aapt-orig" "$" 

Или даже проще:

#!/usr/bin/env bash exec "$/aapt-orig" "$1" --custom-package com.leumi.leumiwallet "${@:2}" 
Примечание: `echo $ 0 | xargs dirname`? *В самом деле?* grawity 11 лет назад 2
По некоторым причинам, которые, я уверен, @grawity поймет лучше, чем я, использование двойных кавычек также работает: `./aapt action" "/ Users / bankleumi / some dir /" "another_param` terdon 11 лет назад 0
@terdon: Я не уверен, * как * это будет работать. После удаления кавычек bash `" "foo bar" "baz` в точности совпадает с` foo bar baz`, и aapt получает его как три аргумента из одного слова. grawity 11 лет назад 0
Понятия не имею, @grawity, просто попробовал это по прихоти, и это сработало. Я использовал скрипт в OP и просто заключил в кавычки аргумент CLI, как показано выше. Соответствующим выводом было: `+ echo action --custom-package com.some.package / Users / bankleumi / some dir / another_param`. Версия Bash: `GNU bash, версия 4.2.36 (1) -релиз (x86_64-pc-linux-gnu)` terdon 11 лет назад 0
1
Rainer Blome

Это должно работать с большим количеством оболочек и может быть проще для понимания:

#!/bin/sh first="$1"; shift; exec "`dirname '$0'`/aapt-orig" "$first" --custom-package com.foo.bar "$@"; 

Обратите внимание, что это работает, потому что оболочки обрабатывают "$@"специально, см. Раздел «Специальные параметры» на справочной странице Bash.