Как заставить bash ставить подсказку на новой строке после команды cat?

17

Что я получаю:

host:~ user$ cat example.txt
some texthost:~ stas$

Что я хочу получить:

host:~ user$ cat example.txt
some text
host:~ stas$

Есть ли способ заставить меня catвести себя так?

Я использую Bash на Mac OS X.

Станислав Шабалин
источник

Ответы:

15

Большинство инструментов Unix хорошо работают с текстовыми файлами. Текстовый файл состоит из последовательности строк. Строка состоит из последовательности печатных символов, заканчивающихся символом новой строки. В частности, последний символ непустого текстового файла всегда является символом новой строки. Очевидно, example.txtсодержит только some textбез окончательного перевода строки, так что это не текстовый файл.

catделает простую работу; превращение произвольных файлов в текстовые файлы не является частью этой работы. Некоторые другие инструменты всегда превращают их ввод в текстовые файлы; если вы не уверены, что отображаемый файл заканчивается новой строкой, попробуйте запустить awk 1вместо cat.

Вы можете сделать так, чтобы bash отображал подсказку на следующей строке, если предыдущая команда оставила курсор где-то, кроме последнего поля. Поместите это в свое .bashrc(вариант от GetFree предложения Денниса Уильямсона ):

shopt -s promptvars
PS1='$(printf "%$((COLUMNS-1))s\r")'$PS1
Жиль "ТАК - прекрати быть злым"
источник
Большое спасибо за рабочее решение и краткое объяснение! Я понимаю, что это немного для бедных cat, поэтому я буду держать это в качестве последнего средства для того времени, когда эта проблема снова начинает беспокоить меня.
Станислав Шабалин
Поскольку это предпочтение bash, может ли оно нарушать команды конвейера?
Станислав Шабалин
1
@StanislavShabalin Это не влияет на трубопровод, только на подсказку.
Жиль "ТАК ... перестать быть злым"
Мне нужно удалить «-1» после «КОЛОННЫ», чтобы это работало правильно.
Рафак
Это решение вызывает перемещение запроса при изменении размера окна терминала. Я обнаружил, что для надежной работы мне нужно было ввести текущий столбец PROMPT_COMMANDи, если он не равен 0, использовать \nсимвол новой строки ( ) в качестве первого символа PS1.
Брайан Донован
10

Я предпочитаю следующий метод ...

cat example.txt ; echo

Это не оценивает содержимое example.txtили не добавляет новую строку. Это просто повторяет новую строку после того, как кошка готова, ее легко запомнить, и никто не задумывается о том, правильно ли они используют сильные или слабые цитаты.

Единственным недостатком, на самом деле, является то, что вы получите дополнительный символ новой строки, если файл имеет собственный завершающий символ новой строки.

амосс
источник
7

Я начал использовать ответ @ Gilles, но обнаружил, что если терминал изменяет количество столбцов, приглашение больше не будет находиться в начале строки, как ожидалось. Это может произойти по разным причинам, включая tmux / screen split, ручное изменение размера контейнера GUI, изменения шрифтов и т. Д.

То, что я действительно хотел, было что-то, что добавило бы новую строку, если терминал начал печатать свою подсказку в чем-то кроме первого столбца. Для этого мне нужно было выяснить, как получить текущий столбец, который я использовал для получения этого ответа . Окончательная рабочая подсказка ниже:

###
# Configure PS1 by using the old value but ensuring it starts on a new line.
###
__configure_prompt() {
  PS1=""

  if [ "$(__get_terminal_column)" != 0 ]; then
    PS1="\n"
  fi

  PS1+="$PS1_WITHOUT_PREPENDED_NEWLINE"
}

###
# Get the current terminal column value.
#
# From /programming//a/2575525/549363.
###
__get_terminal_column() {
  exec < /dev/tty
  local oldstty=$(stty -g)
  stty raw -echo min 0
  echo -en "\033[6n" > /dev/tty
  local pos
  IFS=';' read -r -d R -a pos
  stty $oldstty
  echo "$((${pos[1]} - 1))"
}

# Save the current PS1 for later.
PS1_WITHOUT_PREPENDED_NEWLINE="$PS1"

# Use our prompt configuration function, preserving whatever existing
# PROMPT_COMMAND might be configured.
PROMPT_COMMAND="__configure_prompt;$PROMPT_COMMAND"
Брайан Донован
источник
Я использую это решение, но когда я пытаюсь вставить многострочные команды в мою оболочку, кажется, что в конечном итоге все части / все строки остаются после вставки первой. Есть ли какое-то решение этого?
только
@onlynone, возможно, ваши команды не сбрасываются отдельно и вовремя __get_terminal_column?
Андробин
Вместо того, чтобы PS1="\n"просто echoизменить и не нужно ничего менять PS1.
Андробин
4

Проблема в том, что ваш example.txt не имеет новой строки в конце вашего файла.

Бонси Скотт
источник
2
Дело в том, что мне все равно, есть ли в конце строка перевода строки или нет. Я хочу, чтобы вывод кота был более четким, а не таким разрушительным :-) И я понимаю, что это не catработа, поэтому, вероятно, я ищу какой-то обходной путь.
Станислав Шабалин
1
Это такой не ответ, example.txtне имеющий новой строки в конце файла, вот и весь вопрос.
Виллем д'Азелер
2

Если вы настаиваете на использовании cat, это работает для обоих типов файлов, с и без новой строки в конце:

echo "`cat example.txt`"

Вы можете превратить его в функцию с именем по вашему выбору (даже cat) в вашем .bashrc:

cat1(){ echo "`/bin/cat $@`";}
woodengod
источник
1
Теперь это слишком много, даже если это работает ;-) Спасибо, хотя!
Станислав Шабалин
0

Вы также можете добавить в .bashrc

PROMPT_COMMAND="printf '\n';$PROMPT_COMMAND"

работает для меня.

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