Понимание IFS

svn switch --relocate ожидает находить тот же репозиторий в новом URL, не другой.

Вы использовали svnsync создать новый репозиторий? В этом случае можно использовать svnadmin setuuid использовать тот же uuid в качестве старого репозитория. Согласно svnsync документации в книге svn, это должно позволить Вам снова использовать существующие рабочие копии.

74
23.05.2017, 14:33
4 ответа
  1. Да, они - то же.
  2. Да.
  3. В ударе и подобных оболочках, Вы могли сделать что-то как IFS=$' \t\n'. Иначе Вы могли ввести коды элемента управления литерал при помощи [space] CTRL+V [tab] CTRL+V [enter]. Если Вы планируете сделать это, однако, лучше использовать другую переменную для временного хранения старого IFS значение, и затем восстанавливает его впоследствии (или временно переопределяет его для одной команды при помощи var=foo command синтаксис).
    • Первый фрагмент кода поместит все чтение строки, дословно, в $line, как нет никаких разделителей полей для выполнения разделения слова для. Примите во внимание однако, что, так как много оболочек используют cstrings для хранения строк, первая инстанция NUL может все еще вызвать появление его преждевременно завершаемый.
    • Второй фрагмент кода не может поместить точную копию входа в $line. Например, если будет несколько последовательных разделителей полей, то они будут превращены в единственный экземпляр первого элемента. Это часто распознается как потеря окружающего пробела.
    • Третий фрагмент кода сделает то же, поскольку второе, кроме него только разделит на пространстве (не обычное пространство, вкладка или новая строка).
29
27.01.2020, 19:31
  • 1
    Ответ на Q2 является неправильным: пустое IFS и сброс IFS очень отличаются. Ответ на Q4 является частично неправильным: внутренние разделители не затронуты здесь, только ведя и запаздывающие. –  Gilles 'SO- stop being evil' 14.12.2011, 14:06
  • 2
    @Gilles: В Q2 ни одно из трех данных наименований не относится к сбросу IFS, все они имеют в виду IFS=. –  Stéphane Gimenez 14.12.2011, 15:00
  • 3
    @Gilles В Q2, я никогда не говорил, что они были тем же. И внутренние разделители затронуты, как показано здесь: IFS=' ' ; foo=( bar baz qux ) ; echo "${#foo[@]}". (Er, что? Там должно быть несколько разделителей пространства, ТАКИМ ОБРАЗОМ, механизм продолжает разделять их). –  Chris Down 14.12.2011, 18:05
  • 4
    @StéphaneGimenez, Chris: О, право, извините о Q2, я неправильно читал вопрос. Для Q4 мы говорим о read; последняя переменная захватывает все, что это оставляют за исключением последнего разделителя и оставляет внутренние разделители внутри. –  Gilles 'SO- stop being evil' 15.12.2011, 17:25
  • 5
    Gilles частично корректен о пробелах, не удаляемых чтением. Прочитайте мой ответ для деталей. –   07.08.2015, 02:28

Q1: Да. “Полевое разделение” и “разделение слова” являются двумя условиями для того же понятия.

Q2: да. Если IFS сброшен (т.е. после unset IFS), это эквивалентно IFS быть установленным на $' \t\n' (пространство, вкладка и новая строка). Если IFS установлен на пустое значение (это - то, что “пустой указатель” означает здесь) (т.е. после IFS= или IFS='' или IFS=""), никакое полевое разделение не выполняется вообще (и $*, который обычно использует первый символ $IFS, использует пробел).

Q3: Если Вы хотите иметь значение по умолчанию IFS поведение, можно использовать unset IFS. Если Вы хотите установить IFS явно к этому значению по умолчанию, можно поместить пространство буквенных символов, вкладку, новую строку в одинарных кавычках. В ksh93, ударе или zsh, можно использовать IFS=$' \t\n'. Портативно, если Вы не хотите иметь литеральный символ табуляции в своем исходном файле, можно использовать

IFS=" $(echo t | tr t \\t)
"

Q4: с IFS набор к пустому значению, read -r line наборы line к целой строке кроме ее новой строки завершения. С IFS=" ", пробелы вначале и в конце строки обрезаются. Со значением по умолчанию IFS, вкладки и пробелы обрезаются.

22
27.01.2020, 19:31
  • 1
    является частично неправильным. Если IFS пуста, "к $*" присоединяются без разделителей. (для $@, существуют некоторые изменения между оболочками в контекстах несписка как IFS=; var=$@). Нужно отметить, что, когда IFS пуста, никакое разделение слова не выполняется, но $var все еще не расширяется ни до какого аргумента вместо пустого аргумента, когда $var пуст, и globbing все еще применяется, таким образом, все еще необходимо заключить переменные в кавычки (даже при отключении globbing) –  Stéphane Chazelas 09.02.2013, 00:19

unset IFS действительно очищает IFS, даже если IFS, как после этого предполагают, является "\t\n":

$ echo "'$IFS'"
'   
'
$ IFS=""
$ echo "'$IFS'"
''
$ unset IFS
$ echo "'$IFS'"
''
$ IFS=$' \t\n'
$ echo "'$IFS'"
'   
'
$

Протестированный на версиях 4.2.45 и 3.2.25 удара с тем же поведением.

4
27.01.2020, 19:31

Q1. Разделение поля.

Разделение полей - это то же самое, что разделение слов?

Да, оба указывают на одну и ту же идею.

Q2: Когда IFS null ?.

Параметр IFS = '' такой же, как null, то же самое, что и пустая строка?

Да, все три означают одно и то же: разделение полей / слов выполняться не будет. {{ 1}} Кроме того, это влияет на поля печати (как в случае echo "$ *" ), все поля будут объединены вместе без пробелов.

Q3: (часть a) Отключить IFS.

В спецификации POSIX я прочитал следующее :

Если IFS не установлен, оболочка должна вести себя так, как если бы значение IFS было <пробел> <новая строка > .

Что в точности эквивалентно:

При неустановленном IFS оболочка должна вести себя так, как если бы IFS был установлен по умолчанию.

Это означает, что «Разделение полей» будет точно таким же со значением IFS по умолчанию или не задано.
Это НЕ означает, что IFS будет работать одинаково во всех условиях. Более конкретно, выполнение OldIFS = $ IFS установит переменную OldIFS до null , а не значение по умолчанию. И попытка вернуть IFS, например, IFS = OldIFS установит IFS в ноль, а не оставит его неустановленным, как это было раньше. Осторожно !!.

Q3: (часть b) Восстановить IFS.

Как мне восстановить значение IFS по умолчанию. Скажем, я хочу восстановить значение IFS по умолчанию.Как мне это сделать? (более конкретно, как мне сослаться на и ?)

Для zsh, ksh и bash (AFAIK) IFS может быть установлен на значение по умолчанию:

IFS=$' \t\n'        # works with zsh, ksh, bash.

Готово, больше ничего читать не нужно.

Но если вам нужно переустановить IFS для sh, это может стать сложным.

Давайте посмотрим от самого простого к законченному без недостатков (кроме сложности).

1.- Отключить IFS.

Мы могли бы просто отключить IFS (прочтите Q3, часть a, выше).

2.- Поменять местами символы.

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

Установите IFS на <пробел> <новая строка> :

sh -c 'IFS=$(echo " \n\t"); printf "%s" "$IFS"|xxd'      # Works.

3.- Простой? Решение:

Если есть дочерние сценарии, которым необходимо правильно установить IFS, вы всегда можете вручную написать:

IFS='   
'

Где последовательность, введенная вручную, была: IFS = ' пробел tab новая строка ', последовательность, которая была правильно введена выше (если вам нужно подтвердить, отредактируйте этот ответ). Но копирование / вставка из вашего браузера не работает, потому что браузер сжимает / скрывает пробелы. Это затрудняет совместное использование кода, как написано выше.

4.- Полное решение.

Для написания кода, который можно безопасно скопировать, обычно требуются однозначные печатные escape-последовательности.

Нам нужен код, который «производит» ожидаемое значение. Но, даже если концептуально верен, этот код НЕ будет устанавливать завершающий \ n :

sh -c 'IFS=$(echo " \t\n"); printf "%s" "$IFS"|xxd'      # wrong.

Это происходит потому, что в большинстве командных интерпретаторов все завершающие символы новой строки $ (...) или `...` подстановки команд удаляются при расширении.

Нам нужно использовать трюк для sh:

sh -c 'IFS="$(printf " \t\nx")"; IFS="${IFS%x}"; printf "$IFS"|xxd'  # Correct.

Альтернативным способом может быть установка IFS как значение среды из bash (например), а затем вызов sh (его версии, которые принимают IFS должен быть установлен через среду), например:

env IFS=$' \t\n' sh -c 'printf "%s" "$IFS"|xxd'

Короче говоря, sh делает сброс IFS по умолчанию довольно странным приключением.

Q4: В реальном коде:

И, наконец, как этот код:

 в то время как IFS = read -r line 
do 
echo $ line 
done < / path_to_text_file 
 

ведет себя, если мы изменим первую строку на

 при чтении -r line # Использовать значение IFS по умолчанию 
 

или:

 при IFS = '' read -r line 
 

Во-первых: я не знаю, есть ли echo $ line (с var NOT в кавычках) на porpouse или нет. {{1} } Он вводит второй уровень «разделения полей», которого у чтения нет. Так что я отвечу на оба. :)

С помощью этого кода (чтобы вы могли подтвердить). Вам понадобится полезный xxd :

#!/bin/ksh
# Correctly set IFS as described above.
defIFS="$(printf " \t\nx")"; defIFS="${defIFS%x}";
IFS="$defIFS"
printf "IFS value: "
printf "%s" "$IFS"| xxd -p

a='   bar   baz   quz   '; l="${#a}"
printf "var value          : %${l}s-" "$a" ; printf "%s\n" "$a" | xxd -p

printf "%s\n" "$a" | while IFS='x' read -r line; do
    printf "IFS --x--          : %${l}s-" "$line" ;
    printf "%s" "$line" |xxd -p; done;

printf 'Values      quoted :\n' ""  # With values quoted:
printf "%s\n" "$a" | while IFS='' read -r line; do
    printf "IFS null    quoted : %${l}s-" "$line" ;
    printf "%s" "$line" |xxd -p; done;

printf "%s\n" "$a" | while IFS="$defIFS" read -r line; do
    printf "IFS default quoted : %${l}s-" "$line" ;
    printf "%s" "$line" |xxd -p; done;

unset IFS; printf "%s\n" "$a" | while read -r line; do
    printf "IFS unset   quoted : %${l}s-" "$line" ;
    printf "%s" "$line" |xxd -p; done;
    IFS="$defIFS"   # set IFS back to default.

printf "%s\n" "$a" | while IFS=' ' read -r line; do
    printf "IFS space   quoted : %${l}s-" "$line" ;
    printf "%s" "$line" |xxd -p; done;

printf '%s\n' "Values unquoted :"   # Now with values unquoted:
printf "%s\n" "$a" | while IFS='x' read -r line; do
    printf "IFS --x-- unquoted : "
    printf "%s, " $line; printf "%s," $line |xxd -p; done

printf "%s\n" "$a" | while IFS='' read -r line; do
    printf "IFS null  unquoted : ";
    printf "%s, " $line; printf "%s," $line |xxd -p; done

printf "%s\n" "$a" | while IFS="$defIFS" read -r line; do
    printf "IFS defau unquoted : ";
    printf "%s, " $line; printf "%s," $line |xxd -p; done

unset IFS; printf "%s\n" "$a" | while read -r line; do
    printf "IFS unset unquoted : ";
    printf "%s, " $line; printf "%s," $line |xxd -p; done
    IFS="$defIFS"   # set IFS back to default.

printf "%s\n" "$a" | while IFS=' ' read -r line; do
    printf "IFS space unquoted : ";
    printf "%s, " $line; printf "%s," $line |xxd -p; done

Я получаю:

$ ./stackexchange-Understanding-IFS.sh
IFS value: 20090a
var value          :    bar   baz   quz   -20202062617220202062617a20202071757a2020200a
IFS --x--          :    bar   baz   quz   -20202062617220202062617a20202071757a202020
Values      quoted :
IFS null    quoted :    bar   baz   quz   -20202062617220202062617a20202071757a202020
IFS default quoted :       bar   baz   quz-62617220202062617a20202071757a
IFS unset   quoted :       bar   baz   quz-62617220202062617a20202071757a
IFS space   quoted :       bar   baz   quz-62617220202062617a20202071757a
Values unquoted :
IFS --x-- unquoted : bar, baz, quz, 6261722c62617a2c71757a2c
IFS null  unquoted : bar, baz, quz, 6261722c62617a2c71757a2c
IFS defau unquoted : bar, baz, quz, 6261722c62617a2c71757a2c
IFS unset unquoted : bar, baz, quz, 6261722c62617a2c71757a2c
IFS space unquoted : bar, baz, quz, 6261722c62617a2c71757a2c

Первое значение - это просто правильное значение IFS = ' пробел tab newline '

Следующая строка - это все шестнадцатеричные значения, которые имеет var $ a , и новая строка «0a» в конце, поскольку она будет передаваться каждой команде чтения. .

Следующая строка, для которой IFS имеет значение NULL, не выполняет никакого «разделения полей», но новая строка удаляется (как и ожидалось).

Следующие три строки, поскольку IFS содержит пробел, удаляют начальные пробелы и устанавливают в строке var значение остатка баланса.

Последние четыре строки показывают, что будет делать переменная без кавычек.Значения будут разделены на (несколько) пробелов и будут напечатаны как: bar, baz, qux,

15
27.01.2020, 19:31

Теги

Похожие вопросы