Node.js: drukowanie na konsoli bez końca nowej linii?

683

Czy istnieje metoda drukowania na konsoli bez końcowego znaku nowej linii? consoleObiekt dokumentacja nic nie powiedzieć, że w sprawie:

console.log()

Drukuje na standardowym ekranie z nową linią. Ta funkcja może przyjmować wiele argumentów w printf()podobny sposób. Przykład:

console.log('count: %d', count);

Jeśli elementy formujące nie zostaną znalezione w pierwszym ciągu, wówczas util.inspectzostanie użyty dla każdego argumentu.

Evan Carroll
źródło

Odpowiedzi:

1058

Możesz użyć process.stdout.write():

process.stdout.write("hello: ");

Szczegółowe informacje można znaleźć w dokumentacji .

onteria_
źródło
7
To rozwiązało dla mnie odwrotny problem. console.logdrukowałem \ndosłownie, kiedy chciałem, aby wydrukował znak nowej linii.
Paul
@Paulpro nie jest znakiem nowej linii?
Alexander Mills,
3
@AlexMills Jest to sekwencja ucieczki dla znaku nowej linii, ale sama nie jest znakiem nowej linii. ` followed by an Dostawałem dosłowne „ n”, kiedy chciałem stworzyć prawdziwy znak nowej linii.
Paul,
379

Ponadto, jeśli chcesz zastąpić wiadomości w tym samym wierszu, na przykład podczas odliczania, możesz dodać „\ r” na końcu ciągu.

process.stdout.write("Downloading " + data.length + " bytes\r");
defvol
źródło
18
Chociaż nie jest to odpowiedź na pytanie, jest to niesamowita odpowiedź. Nie mogę się doczekać, aby spróbować.
longda
8
Dla mnie to nie działa w systemie Windows. Ale działa świetnie na nie-dows.
chowey
45
W systemie Windows można użyć równoważnego kodu „\ 033 [0G”, jak w:process.stdout.write("Downloading " + data.length + " bytes\033[0G");
GarciadelCastillo
19
Aby dokonać ansi kod ucieczki podane powyżej w komentarzu przez @GarciadelCastillo do pracy w trybie ścisłym, wymienić ósemkowy dosłowne \033z dosłownym hex \x1btak: \x1b[0G. (która działa zarówno z kodem ścisłym, jak i nie ścisłym)
niektóre
7
Po prostu umieść \ r na początku, a nie na końcu łańcucha, aby działał w systemie Windows.
daremkd
20

W konsoli Windows (także Linux) należy zastąpić '\r'go równoważnym kodem \033[0G:

process.stdout.write('ok\033[0G');

Używa sekwencji ucieczki terminala VT220 do wysłania kursora do pierwszej kolumny.

Yan Te
źródło
1
Jak cofnąłbyś się o wiele linii zamiast tylko bieżącej? Top program wydaje się być w stanie przesłonić cały mój bufor przy włączonym silniku i przywraca to, co było tam, kiedy to zrobić. Czy ktoś wie jak to robi? i.imgur.com/AtCmEjn.gif
Chev
Myślę, że prawdopodobnie używa czegoś takiego: github.com/mscdex/node-ncurses github.com/chjj/blessed
Brandon
1
Działa, ale dostaję również kursor, [\] 39a kursor jest podświetlony na pierwszym znaku:var spinner = '|/-\\'.split('');process.stdout.write("["+this.randomElement(spinner)+"] "+message+"\033[0G");
loretoparisi
1
@Chev Top jest wyjątkowy, a nie coś, co można napisać za pomocą kodów specjalnych ANSI. Rzeczywiście używa ncurses, dlatego nie znajdziesz go w systemach wbudowanych, które nie mają dużych bibliotek C
cat
1
@Chev: Większość ludzi odradza ci granie na sztywno zakodowanych sekwencjach ucieczki z powodu własnego FUD, ale prawie wszyscy używają teraz VT100, więc zgodność nie jest już tak naprawdę problemem. Funkcjonalność, o której mówisz, to zachowanie „alternatywnego ekranu”. Podstawowe wprowadzenie można znaleźć w man console_codes(w systemie Linux lub online), a moją ulubioną referencją jest www2.phys.canterbury.ac.nz/dept/docs/manuals/unix/DEC_4.0e_Docs/… (99% jego zawartości nadal działa) . Tylko zastrzeżenie: przed szerokim wdrożeniem przygotuj się do przetestowania dowolnych eksperymentów na kilku różnych terminalach.
i336_
18

W ramach rozszerzenia / udoskonalenia genialnego dodatku dokonanego przez @rodowi powyżej dotyczącego możliwości zastąpienia wiersza:

process.stdout.write("Downloading " + data.length + " bytes\r");

Jeśli nie chcesz, aby kursor terminala znajdował się przy pierwszym znaku, jak widziałem w moim kodzie, rozważ wykonanie następujących czynności:

let dots = ''
process.stdout.write(`Loading `)

let tmrID = setInterval(() => {
  dots += '.'
  process.stdout.write(`\rLoading ${dots}`)
}, 1000)

setTimeout(() => {
  clearInterval(tmrID)
  console.log(`\rLoaded in [3500 ms]`)
}, 3500)

Umieszczając \rprzed następną instrukcją drukowania kursor jest resetowany tuż przed zastąpieniem ciągu zastępującego ciąg poprzedni.

Mraxus
źródło
13

util.print może być stosowany również. Przeczytaj: http://nodejs.org/api/util.html#util_util_print

util.print ([...]) # Funkcja wyjścia synchronicznego. Blokuje proces, rzuca każdy argument na ciąg, a następnie wyprowadza na standardowe wyjście. Nie umieszcza nowego wiersza po każdym argumencie.

Przykład:

// get total length
var len = parseInt(response.headers['content-length'], 10);
var cur = 0;

// handle the response
response.on('data', function(chunk) {
  cur += chunk.length;
  util.print("Downloading " + (100.0 * cur / len).toFixed(2) + "% " + cur + " bytes\r");
});
douyw
źródło
39
util.printjest przestarzałe
Petr Peller
(node:7616) DeprecationWarning: util.print is deprecated. Use console.log instead.
Zielony
10

Wydaje się, że istnieje wiele odpowiedzi sugerujących:

process.stdout.write

Dzienniki błędów powinny być emitowane:

process.stderr

Zamiast tego użyj:

console.error

Dla każdego, kto zastanawia się, dlaczego process.stdout.write('\033[0G');nic nie zrobił, to dlatego, że stdoutjest buforowany i musisz poczekać na drainwydarzenie ( więcej informacji ).

Jeśli zapis zwraca false, wywoła drainzdarzenie.

Ahmed Masud
źródło
4

Żadne z tych rozwiązań nie działa dla mnie process.stdout.write('ok\033[0G')i po prostu używa'\r' nowej linii, ale nie zastępuj w Mac OSX 10.9.2.

EDYCJA: Musiałem użyć tego, aby zastąpić bieżącą linię:

process.stdout.write('\033[0G');
process.stdout.write('newstuff');
Tyguy7
źródło
4

Podczas używania trybu ścisłego wystąpił następujący błąd:

Błąd węzła: „Literały ósemkowe nie są dozwolone w trybie ścisłym”.

Działa następujące rozwiązanie ( źródło ):

process.stdout.write("received: " + bytesReceived + "\x1B[0G");
blablabla
źródło
Zmień dosłowny format tobsone. Lub inny format liczbowy
FrancescoMM