(git) Bash: чем именно разрыв строки отличается от \n в переменной?

Мои извинения, я, должно быть, допустил некоторые ошибки при выполнении первоначальных тестов, так как после объединения всего в один скрипт вывод xxd действительно всегда соответствует вводу stdouput.

Полный сценарий находится здесь: https://pastebin.pl/view/454913ec. Я обновляю свой вопрос и оставляю исходный (но неправильный) вопрос ниже.

Вывод сценария, который я получаю, следующий:

      $ ./test.sh
# Case 1A: echo -n $TEST1
hello world
00000000: 6865 6c6c 6f20 776f 726c 64              hello world

# Case 1B: echo -n -e $TEST1
hello world
00000000: 6865 6c6c 6f20 776f 726c 64              hello world

# Case 1C: echo -n "$TEST1"
hello
world
00000000: 6865 6c6c 6f0a 776f 726c 64              hello.world

# Case 1D: echo -n -e "$TEST1"
hello
world
00000000: 6865 6c6c 6f0a 776f 726c 64              hello.world

# Case 1E: printf "%s" $TEST1
helloworld
00000000: 6865 6c6c 6f77 6f72 6c64                 helloworld

# Case 1F: $ printf "%s" "$TEST1"
hello
world
00000000: 6865 6c6c 6f0a 776f 726c 64              hello.world

# --------------------------------
# Case 2A: $ echo -n $TEST2
hello\nworld
00000000: 6865 6c6c 6f5c 6e77 6f72 6c64            hello\nworld

# Case 2B: echo -n -e $TEST2
hello
world
00000000: 6865 6c6c 6f0a 776f 726c 64              hello.world

# Case 2C: echo -n "$TEST2"
hello\nworld
00000000: 6865 6c6c 6f5c 6e77 6f72 6c64            hello\nworld

# Case 2D: echo -n -e "$TEST2"
hello
world
00000000: 6865 6c6c 6f0a 776f 726c 64              hello.world

# Case 2E: printf "%s" $TEST2
hello\nworld
00000000: 6865 6c6c 6f5c 6e77 6f72 6c64            hello\nworld

# Case 2F: printf "%s" "$TEST2"
hello\nworld
00000000: 6865 6c6c 6f5c 6e77 6f72 6c64            hello\nworld

Таким образом, вывод xxd, по крайней мере, одинаков для того же вывода стандартного вывода. Еще раз извините за это!

Итак, оставшиеся у меня вопросы:

  1. Почему результат на выходеhelloworld

  2. Какие последовательности байтов ДЕЙСТВИТЕЛЬНО содержатся в TEST1 и TEST2, и какой способ это выяснить?

  3. Как я могу заставить printf интерпретировать тип новой строки, закодированный в TEST2?

  4. является ли следующее присваивание переносимым (в том смысле, что оно всегда будет приводить к одному и тому же двоичному содержимому переменных?

$ TEST1="привет

мир" $ TEST2="привет\nмир"

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


Оригинальный (но неправильный) вопрос:

Я выполнил следующие тесты, используя git bash:

      $ TEST1="hello
> world"
$ TEST2="hello\nworld"


# Case 1A:
$ echo -n $TEST1
hello world
$ echo -n $TEST1 | xxd
00000000: 6865 6c6c 6f20 776f 726c 64              hello world

# Case 1B:
$ echo -n -e $TEST1
hello world
$ echo -n -e $TEST1 | xxd
00000000: 6865 6c6c 6f20 776f 726c 64              hello world

# Case 1C:
$ echo -n "$TEST1"
hello
world
$ echo -n "$TEST1" | xxd
00000000: 6865 6c6c 6f0a 776f 726c 64              hello.world

# Case 1D:
$ echo -n -e "$TEST1"
hello
world
$ echo -n -e "$TEST1" | xxd
00000000: 6865 6c6c 6f0a 776f 726c 64              hello.world

# Case 1E:
$ printf "%s" $TEST1
helloworld
$ printf "%s" $TEST1 | xxd
00000000: 6865 6c6c 6f77 6f72 6c64                 helloworld

# Case 1F:
$ printf "%s" "$TEST1"
hello
world
$ printf "%s" "$TEST1" | xxd
00000000: 6865 6c6c 6f0a 776f 726c 64              hello.world
$

# --------------------------------

# Case 2A:
$ echo -n $TEST2
hello\nworld
$ echo -n $TEST2 | xxd
00000000: 6865 6c6c 6f20 776f 726c 64              hello world

# Case 2B:
$ echo -n -e $TEST2
hello
world
$ echo -n -e $TEST2 | xxd
00000000: 6865 6c6c 6f20 776f 726c 64              hello world

# Case 2C:
$ echo -n "$TEST2"
hello\nworld
$ echo -n "$TEST2" | xxd
00000000: 6865 6c6c 6f0a 776f 726c 64              hello.world

# Case 2D:
$ echo -n -e "$TEST2"
hello
world
$ echo -n -e "$TEST2" | xxd
00000000: 6865 6c6c 6f0a 776f 726c 64              hello.world

# Case 2E:
$ printf "%s" $TEST2
hello\nworld
$ printf "%s" $TEST2 | xxd
00000000: 6865 6c6c 6f77 6f72 6c64                 helloworld

# Case 2F:
$ printf "%s" "$TEST2"
hello\nworld
$ printf "%s" "$TEST2" | xxd
00000000: 6865 6c6c 6f0a 776f 726c 64              hello.world
$

во-первых: меня это расстраивает. Также мне хотелось бы добавить несколько собственных цветов в кодовые блоки в stackoverflow, чтобы лучше визуализировать проблему (например, раскрасить одинаковые выходные данные в одинаковые цвета).

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

Итак, некоторые вещи, которые меня смущают, например:

  1. Несмотря на то, что напечатанные выходные данные стандартного вывода различаются для и (например,Case 1Aприводит к получению другого результата, чемcase 2A), кажется, что фактические байты, которые xxd получает в качестве входных данных, идентичны во всех соответствующих случаях (я имею в виду все соответствующие случаиCase 1xвсегда имеет тот же вывод xxd, что иCase 2x, даже если соответствующие выходные данные стандартного вывода одной и той же команды не равны). Как это возможно?

  2. Очевидно, что содержимое и должно каким-то образом отличаться, иначе было бы невозможно, чтобы их отображение/печать могли привести к различным выводам стандартного вывода. Итак, как я могу правильно вывести ДЕЙСТВИТЕЛЬНЫЕ биты (в шестнадцатеричном формате или в каком-то другом виде, не имеет значения, если это четкое представление фактического содержимого переменной), содержащиеся в этих переменных?

  3. случаи будут указывать на то, что xxd получает символ новой строки ascii именно тогда, когда в распечатке также отображается разрыв строки. Однако в случаяхCase 2Bпечатает разрыв строки, но не приводит к появлению символа иCase 2Fне печатает перенос строки, однако приводит к0Aхарактер

Я понимаю, что разрыв строки в переменных and закодирован по-разному, и что при повторении двойных кавычек кажется, что расширяется (это правильная терминология?) тип разрыва строки, содержащийся вTEST1, хотя флаг -e для echo, похоже, интерпретирует тип разрыва строки, закодированный в , но это не объясняет выходные данные xxd, а также случаи printf.

  1. ПочемуCase 1Eрезультат в

             $ printf "%s" $TEST1
     helloworld
    
  2. Как заставить printf применять разрывы строк, закодированные вTEST2переменная?

  3. Какой урок здесь следует извлечь наиболее важным?

примечания: я воздержался от добавления

      $ TEST3="hello\n
world"

чтобы вопрос был кратким.

Я также тестировал использование одинарных кавычек ' ' вместо двойных кавычек " " при определении переменных, что, похоже, не влияет на результаты.

1 ответ

Я не уверен, что этим объясняются все различия, но я считаю, что разница в том, что TEST1 содержит возврат каретки(), а не перевод строки().

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

Вы можете увидеть различия по следующему коду:

      $ echo $TEST1 | od -w32 -t x1c
0000000  68  65  6c  6c  6f  20  3e  20  77  6f  72  6c  64  0a
          h   e   l   l   o       >       w   o   r   l   d  \n

$ echo $TEST2 | od -w32 -t x1c
0000000  68  65  6c  6c  6f  5c  6e  77  6f  72  6c  64  0a
          h   e   l   l   o   \   n   w   o   r   l   d  \n

Следует также помнить, чтоиинтерпретируются терминалом, а не Bash. Это означает, что смешивание их обработки с помощью Bash и терминала может привести к различным результатам в зависимости от порядка выполнения операций.

Другие вопросы по тегам