Jak sprawić, aby bash wstawił monit w nowym wierszu po poleceniu kota?


17

Co dostaję:

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

Co chcę uzyskać:

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

Czy mogę w ten sposób catzachowywać się w ten sposób?

Używam bash na Mac OS X.

Odpowiedzi:


15

Większość narzędzi uniksowych jest zaprojektowana do pracy z plikami tekstowymi. Plik tekstowy składa się z sekwencji wierszy. Linia składa się z sekwencji drukowalnych znaków kończących się znakiem nowej linii. W szczególności ostatnim znakiem niepustego pliku tekstowego jest zawsze znak nowej linii. Oczywiście example.txtzawiera tylko some textbez ostatniej nowej linii, więc nie jest to plik tekstowy.

catwykonuje prostą pracę; przekształcanie dowolnych plików w pliki tekstowe nie jest częścią tego zadania. Niektóre inne narzędzia zawsze przekształcają dane wejściowe w pliki tekstowe; jeśli nie masz pewności, czy wyświetlany plik kończy się nową linią, spróbuj uruchomić awk 1zamiast cat.

Możesz sprawić, by bash wyświetlił monit w następnym wierszu, jeśli poprzednie polecenie opuściło kursor w miejscu innym niż ostatni margines. Umieść to w swoim .bashrc(wariant GetFree propozycji Dennisa Williamsona ):

shopt -s promptvars
PS1='$(printf "%$((COLUMNS-1))s\r")'$PS1

Dziękuję bardzo za działające rozwiązanie i zwięzłe wyjaśnienie! Rozumiem, że to trochę dla biednych cat, więc zachowam to jako ostateczność na czas, gdy ten problem zacznie mnie ponownie niepokoić.
— Stanislav Shabalin

Ponieważ jest to preferencja bash, czy może złamać polecenia potokowe?
— Stanislav Shabalin

1
@StanislavShabalin To nie wpływa na orurowanie, tylko na monit.
— Gilles „SO- przestań być zły”

Muszę usunąć „-1” po „KOLUMNACH”, aby to działało poprawnie.
— rafak

To rozwiązanie powoduje przesuwanie monitu podczas zmiany rozmiaru okna terminala. Odkryłem, że aby to działało niezawodnie, musiałem pobrać bieżącą kolumnę PROMPT_COMMANDi, jeśli nie jest to 0, użyj \nznaku nowej linii ( ) jako pierwszego znaku PS1.
— Brian Donovan,

10

Wolę następującą metodę ...

cat example.txt ; echo

To nie ocenia zawartości example.txtani nie dodaje nowego wiersza. To tylko echo nowego wiersza po skończeniu kota, jest łatwe do zapamiętania i nikt nie zastanawia się, czy poprawnie używa silnych, czy słabych cytatów.

Jedynym minusem jest to, że dostaniesz dodatkową linię nowej linii, jeśli plik ma własną linię końcową.


7

Zacząłem używać odpowiedzi @ Gilles, ale stwierdziłem, że jeśli terminal zmieni liczbę kolumn, monit nie będzie już na początku wiersza, jak oczekiwano. Może się to zdarzyć z różnych powodów, w tym podziałów tmux / screen, ręcznego zmieniania rozmiaru kontenera GUI, zmian czcionek itp.

To, czego naprawdę chciałem, to coś, co dodałoby nowy wiersz, gdyby terminal zaczął drukować swój monit w innym miejscu niż pierwsza kolumna. Aby to zrobić, musiałem dowiedzieć się, jak uzyskać bieżącą kolumnę, której użyłem tej odpowiedzi . Ostateczna konfiguracja monitów roboczych jest poniżej:

###
# 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"

Korzystam z tego rozwiązania, ale kiedy próbuję wkleić do powłoki polecenia zawierające wiele wierszy, wydaje się, że kończą część / wszystkie linie po wklejeniu pierwszego. Czy jest na to jakieś rozwiązanie?
— tylko

@onlynone być może twoje polecenia nie są wykonywane indywidualnie i na czas __get_terminal_column?
— Androbin,

Zamiast tego po PS1="\n"prostu mam echoi nie muszę modyfikować PS1.
— Androbin,

4

Problemem może być to, że plik example.txt nie ma nowego wiersza na końcu pliku.


2
Chodzi o to, że nie obchodzi mnie, czy plik ma na końcu nowy wiersz, czy nie. Chcę być w stanie zobaczyć, jak wyjście kota jest bardziej wyraźne, a nie tak destrukcyjne :-) I rozumiem, że to nie catjest praca, więc prawdopodobnie szukam jakiegoś obejścia.
— Stanislav Shabalin

1
To taka brak odpowiedzi, example.txtbrak nowej linii na końcu pliku jest sednem pytania.
— Willem D'Haeseleer,

2

Jeśli nalegasz na użycie cat, działa to w przypadku obu typów plików, z lub bez znaku nowej linii na końcu:

echo "`cat example.txt`"

Możesz zmienić go w funkcję o dowolnej nazwie (nawet cat) w .bashrc:

cat1(){ echo "`/bin/cat $@`";}

1
Teraz to trochę za dużo, nawet jeśli to działa ;-) Dzięki jednak!
— Stanislav Shabalin

0

możesz również dodać do .bashrc

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

pracuje dla mnie.


1
Dodałoby to również dodatkową pustą linię w terminalu, ilekroć narzędzie wysyła coś, co jest poprawnie zakończone przez nową linię.
— Kusalananda

To prawda. Ale to proste, a jeśli nie przeszkadza ci to mieć dodatkową linię ...
— klaus
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.