2016-06-20 5 views
1

У меня есть два конкретных вопроса о IFS. Я знаю, что изменение внутреннего разделителя полей, IFS, изменяет то, что итератор bash перебирает.Почему IFS не влияет на длину массива в bash?

Итак, почему длина массива не изменяется?

Вот мой пример:

delimiter=$1 
strings_to_find=$2 

OIFS=$IFS 
IFS=$delimiter 
echo "the internal field separator is $IFS" 
echo "length of strings_to_find is ${#strings_to_find[@]}" 

for string in ${strings_to_find[@]} 
do 
    echo "string is separated correctly and is $string" 
done 

IFS=$OIFS 

Но почему длина не затронуты новым МФС?

Вторая вещь, которую я не понимаю, заключается в том, как заставить IFS повлиять на входные аргументы.

Скажем, я ожидаю мои входные аргументы выглядеть следующим образом:

./executable_shell_script.sh first_arg:second_arg:third_arg 

И я хочу, чтобы разобрать входные аргументы, установив IFS в :. Как мне это сделать? Установка IFS, похоже, ничего не делает. Я должен делать это неправильно ....?

спасибо.

ответ

3

Баш-массивы, по сути, массивы. Это не строки, которые анализируются по требованию. Когда вы создадите массив, элементы будут такими, какие они есть, и они не изменятся задним числом.

Однако ничто в вашем примере не создает массив. Если вы хотите создать массив из аргумента 2, вам нужно будет использовать другой синтаксис:

strings_to_find=($2) 

Хотя ваш strings_to_find не является массив, Баш позволяет обращаться к нему, как если бы это был массив один элемент. Таким образом, ${#strings_to_find[@]} всегда будет одним, независимо от содержимого strings_to_find. Кроме того, ваша линия:

for string in ${strings_to_find[@]} 

на самом деле не отличается от

for string in $strings_to_find 

Так что расширение не котируется, то это будет слово-сплит, используя текущее значение IFS.

Если вы используете массив, большую часть времени вы не хотите писать for string in ${strings_to_find[@]}, потому что это только что собирает элементы массива в строку, а затем снова разделяет их слово, что теряет исходную структуру массива. Как правило, вы избежите софистика, используя двойные кавычки:

strings_to_find=(...) 
for string in "${strings_to_find[@]}" 

Что касается вашего второго вопроса, то значение IFS не изменяет грамматику оболочки. Независимо от значения IFS слова в команде разделяются пробелами без кавычек. После того, как строка анализируется, оболочка выполняет параметр и другие расширения для каждого слова. Как упоминалось выше, если расширение не цитируется, расширенный текст затем разбивается на строки, используя значение IFS.

Если слово не содержит никаких расширений, словосочетание не выполняется. И даже если слово содержит разложения, слово-расщепление выполняется только на самом разложении.Так что, если вы пишете:

IFS=: 
my_function a:b:c 

my_function будет вызвана с одним аргументом; не происходит расширения, поэтому расщепление слов не происходит. Тем не менее, если вы используете , некорректный внутри функции, расширение $1 будет разбито на слово (если оно разворачивается в контексте, в котором происходит разбиение слов).

С другой стороны,

IFS=: 
args=a:b:c 
my_function $args 

заставит my_function быть вызвана с тремя аргументами.

И, наконец,

IFS=: 
args=c 
my_function a:b:$args 

точно так же, как и при первом вызове, потому что нет в разложении нет :.

2

Это пример сценарий на основе ответа @rici «S:

#!/bin/bash 
fun() 
{ 
    echo "Total Params : " $# 
} 

fun2() 
{ 
    array1=($1) # Word splitting occurs here based on the IFS ':' 
    echo "Total elements in array1 : "${#array1[@]} 
    # Here '#' before array counts the length of the array 
    array2=("$1") # No word splitting because we have enclosed $1 in double quotes 
    echo "Total elements in array2 : "${#array2[@]} 

} 
IFS_OLD="$IFS" 
IFS=$':' #Changing the IFS 
fun a:b:C#Nothing to expand here, so no use of IFS at all. See fun2 at last 
fun a b c 
fun abc 
args="a:b:c" 
fun $args # Expansion! Word splitting occurs with the current IFS ':' here 
fun "$args" # preventing word spliting by enclosing ths string in double quotes 
fun2 a:b:c 

IFS="$IFS_OLD" 

Выходного

Total Params : 1 
Total Params : 3 
Total Params : 1 
Total Params : 3 
Total Params : 1 
Total elements in array1 : 3 
Total elements in array2 : 1 

Bash страница руководство говорит:

The оболочка лечит каждую характер IFS в качестве разделителя и разбивает результаты других расширений на слова на этих символах.

+0

Эта страница 'man' вы нашли эту цитату? Кажется, я не могу найти правильную справочную страницу для этого. – Sother

+1

@Sother: 'Ручная страница bash (1) строка 1758'. В случае возникновения проблем выполните поиск по шаблону в 'bash'. – sjsam

+0

Эта цитата полезна (и я бы подчеркнул «результаты других расширений»), но в последнем абзаце этого раздела («разбиение слов») есть четкое утверждение: «Обратите внимание, что если разложение не происходит, расщепление не происходит выполнено." – rici

 Смежные вопросы

  • Нет связанных вопросов^_^