LINUX.ORG.RU

Загадки шелла

 , ,


1

3

Кто может объяснить такую странность - замену одиночных кавычек двойными, внезапно?

> cat zzz
#!/bin/sh
function ff {
  cat
}
v1=`ff <<EOF
foo'bar'
EOF`
echo v1:=$v1=
v2=$(ff <<EOF
foo'bar'
EOF
)
echo v2:=$v2=
> ./zzz
v1:=foo'bar'=
v2:=foo"bar"=

А если поменять шелл на /bin/bash, то сразу хорошо:
> ./zzz
v1:=foo'bar'=
v2:=foo'bar'=

Дело происходит на AIX. /bin/ksh даёт такой же результат как /bin/sh. Нигде не нашёл объяснения. В линуксе везде нормально, одиночные кавычки всегда. Получается, что ` работает иногда корректнее, чем позиксовый $()
PS На макосе так же, как на линуксе. Не сюрприз.
PPS Нашёл https://stackoverflow.com/questions/25569857/ksh88-changing-single-quotes-to-... . Обтекаю.

★★★★★

Последнее исправление: svu (всего исправлений: 2)

На FreeBSD 13.0-RELEASE не воспроизводится:

 % sh
$ ff() {
> cat
> }
$ v1=`ff <<EOF
> foo'bar'
> EOF`
$ echo v1:=$v1=
v1:=foo'bar'=
$ v2=$(ff <<EOF
> foo'bar'
> EOF
> )
$ echo v2:=$v2=
v2:=foo'bar'=
$^D
 % 

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

mord0d ★★★★★
()

На dash тоже не воспроизводится. Может, надо экранировать кавычки в HEREDOC? В man bash про другие символы идет речь, но все же:

If word is un‐
quoted, all lines of the here-document are subjected to  parameter  ex‐
pansion,  command substitution, and arithmetic expansion, the character
sequence \<newline> is ignored, and \ must be used to quote the charac‐
ters \, $, and `.

В man ksh, что нашел в сети, написано так:

If marker contains no quoted characters, the contents of the temporary file are processed as if enclosed in double quotes each time the command is executed, so parameter, command and arithmetic substitutions are performed, along with backslash (\) escapes for $, ', \ and \newline. 

Я скопировал из man, а там символ 0x27 напечатан. Проверь, что написано в актуальном AIX-овом man.

Zubok ★★★★★
()
Последнее исправление: Zubok (всего исправлений: 4)
Ответ на: комментарий от t184256

а те, кто юзают aix? ...:)

svu ★★★★★
() автор топика
Ответ на: комментарий от svu

Спасибо, этот ман поищу. Но странные люди.

Я man нашел вот тут https://linux.die.net/man/1/ksh и тут символ ', но это странно. Больше похоже на опечатку. Должен быть ` по идее.

А на Oracle вообще какой-то уникодный. Такое ощущение, что когда делали html, то что-то перемудрили с перегоном символов. https://docs.oracle.com/cd/E36784_01/html/E36870/ksh-1.html:

Otherwise, parameter expansion, command substitution, and arithmetic substitution occur, \NEWLINE is ignored, and \ must be used to quote the characters \, $, ‘.

А вот на ksh из Mac OS X вроде бы backquote, как и должно быть. https://www.unix.com/man-page/osx/1/ksh/

Zubok ★★★★★
()
Ответ на: комментарий от svu

Не думаю

Я заметил. Вот, погуглил за тебя

The Korn shell (/usr/bin/ksh) is set up as the default shell. The default or standard shell refers to the shells linked to and started with the /usr/bin/sh command.

pinus_nigra
()
Ответ на: комментарий от pinus_nigra

что-то такое и подозревал

svu ★★★★★
() автор топика
Ответ на: комментарий от svu

Гляди, что на IBM написано:

https://www.ibm.com/docs/en/aix/7.2?topic=ks-input-output-redirection-in-korn...

Вот прямо словами прописано - single quotation mark.

The shell performs parameter substitution for the redirected data. To prevent the shell from interpreting the \, $, and single quotation mark (') characters and the first character of the Word parameter, precede the characters with a \ character.

Zubok ★★★★★
()
Последнее исправление: Zubok (всего исправлений: 1)
Ответ на: комментарий от Zubok

А вот фиг. В этом случае он перестаёт давать двойные, но оставляет backslash. Мдя.

> ./zzz
v1:=foo'bar'=
v2:=foo\'bar\'=
> cat zzz
#!/bin/sh
function ff {
  cat
}
v1=`ff <<EOF
foo'bar'
EOF`
echo v1:=$v1=
v2=$(ff <<EOF
foo\'bar\'
EOF
)
echo v2:=$v2=

«Кто так строит? Кто так строит?!» Фантастические долбодятлы.

svu ★★★★★
() автор топика
Последнее исправление: svu (всего исправлений: 2)
Ответ на: комментарий от pingvinek

А кому сейчас легко?

svu ★★★★★
() автор топика

В ksh в Debian, кстати, тоже нет замены на " Какая-то специфика ksh в AIX.

Zubok ★★★★★
()
Ответ на: комментарий от Zubok

Без разницы. Те же двойные на выходе.
Там, кажется, какой-то древний ksh88. В дебиане небось поновее ksh93.

svu ★★★★★
() автор топика
Ответ на: комментарий от svu

Там, кажется, какой-то древний ksh88. В дебиане небось поновее ksh93.

Ага, 93-й.

Без разницы. Те же двойные на выходе.

Хм, странная ситуация. Получается, что он меняет single quotation marks даже при отключенном экспанде Heredoc:

https://www.ibm.com/docs/en/aix/7.2?topic=ks-input-output-redirection-in-korn...

[n]<<word
   here document
delimiter

If any character in word is quoted, the delimiter is formed by removing the quote on word. The here document lines will not be expanded. Otherwise, the delimiter is the word itself. If no characters in word are quoted, all lines of the here document will be expanded for parameter expansion, command substitution, and arithmetic expansion.

Можно было бы предположить, что он тупо заменяет одинарные кавычки двойными, но это не так, так как если экранировать их, как это написано в документации, то уже не заменяет, но backslash оставляет.

Вообще, меня смущает, что в документации на ksh (AIX) говорится об экранировании одинарных кавычек, а не backquote (в Debian на ksh говорится о backquote, как и везде). Везде, где я посмотрел, речь идет об экранировании backquote, так как понятно, что это расценивается как command substitution, если экспанд Heredoc разрешен. Такое ощущение, что у них какая-то путаница где-то или где-то закралась какая-то особая трактовка одинарных кавычек. Или тупо какой-то баг. Но, блин, в документации написано, что это надо экранировать почему-то. Написано явно и приговорено словами. Зачем это экранировать?

Zubok ★★★★★
()
Последнее исправление: Zubok (всего исправлений: 1)
Ответ на: комментарий от svu

На ksh88 вот есть man у Oracle

https://docs.oracle.com/cd/E36784_01/html/E36870/ksh88-1.html

И тут тоже backquote и ничего про single quotation mark. И также про word (как отключить интерпретацию внутренностей Heredoc):

<< [–]word

    The shell input is read up to a line that is the same as word, or to an EOF. No parameter substitution, command substitution, or file name generation is performed on word. The resulting document, called a here-document, becomes the standard input. If any character of word is quoted, no interpretation is placed upon the characters of the document. Otherwise, parameter and command substitution occur, \ NEWLINE is ignored, and \ must be used to quote the characters \ , $, `, and the first character of word. If − is appended to <<, then all leading tabs are stripped from word and from the document.

Причем зависит баг от контекста. И там и там command substitution. Но для формы `...` работает нормально, а для $(...) нет. https://www.ibm.com/docs/en/aix/7.2?topic=shell-command-substitution-in-korn-...

Zubok ★★★★★
()
Последнее исправление: Zubok (всего исправлений: 3)
Ответ на: комментарий от Zubok

Да, это надо было постараться так сделать, чтобы $() работал хуже и корявее, чем ``

svu ★★★★★
() автор топика
Ответ на: комментарий от svu

Да, это надо было постараться так сделать, чтобы $() работал хуже и корявее, чем ``

Вполне может быть, что баг как раз не в Heredoc, а в том, что в случае $() запускается какой-то поломанный subshell, который меняет кавычки. Может, как-то протестировать без Heredoc?

Zubok ★★★★★
()
Последнее исправление: Zubok (всего исправлений: 1)
Ответ на: комментарий от Zubok

Дело именно в хередоке. Оно приходит в функцию уже сломанным stdin из хередока

> ./zzz
v2:=ok=
> cat zzz
#!/bin/sh
function ff {
  cat > lll
  echo ok
}
v2=$(ff <<EOF
foo'bar'
EOF
)
echo v2:=$v2=
> cat lll
foo"bar"

Или как-то это иначе потестировать?

PS Я попробовал ещё
v2=$(echo "foo'bar'" | ff )

Всё работает нормально, без глупостей.

svu ★★★★★
() автор топика
Ответ на: комментарий от svu

Угу, в heredoc. Интересно, что это, в общем-то некоторые люди описали, но не ясно, как так происходит, что одна и та же конструкция в разных контекстах заменяет кавычки.

Описание проблемы есть, а как такое волшебство происходит, не ясно. Баг, очевидно. https://www.in-ulm.de/~mascheck/various/cmd-subst/:

 In ksh88, at least from release a to i, you have to be aware of a subtle quoting issue inside $( ).
Single quotes in embedded here-documents are converted to double quotes. This means that

    echo $(cat << EOF
         «double quotes»
         'single quotes'
    EOF
    ) 

results in

    «double quotes» «single quotes» 

This happens for the $( ) form but not for the `` form.
This construct is likely to be used if you feed a large block of text to a command and want to save the command output. 
Zubok ★★★★★
()
Ответ на: комментарий от Zubok

вот да. именно так и выглядит. (*матюги*)

svu ★★★★★
() автор топика

AIX

в том же чпуксе в большом числе консольных утил ловил баги, да и пользоваться ими было неудобно - многих возможностей гнутых не хватало. самое прикольное было, когда top запустил - он вообще показывал не правильное кол-во памяти, процов - все перепугались, вскрывали железку и считали физические планки, а ответ был простой - в «настоящих» юниксах консоль сделана наот*сь.

vtVitus ★★★★★
()
Последнее исправление: vtVitus (всего исправлений: 2)
Ответ на: комментарий от vtVitus

все перепугались, вскрывали железку и считали физические планки

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

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.