• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Wykrywanie nowej linii i dopisywanie jej numeru w tekście

Object Storage Arubacloud
0 głosów
901 wizyt
pytanie zadane 18 października 2015 w JavaScript przez ScriptyChris Mędrzec (190,190 p.)
edycja 24 października 2015 przez ScriptyChris

Mam w pliku .txt zapisany tekst, który składa się z kilku linijek (czyli zawiera znaki nowej linii). Wczytałem go przez JavaScript i w konsoli ten tekst mi się pokazuje.

W jaki sposób mogę wykryć, czy i gdzie (w którym miejscu) JavaScript widzi te znaki nowej linii (a jeśli są one traktowane jako znaki spacji, to niech je wykryje)?

Jeśli odczytany tekst wrzucę do div'a, to wyświetla się na całej szerokości okna przeglądarki, bez podziału na linie. Nie wiem dlaczego tak się dzieje, bo w konsoli tekst wyświetla się dokładnie tak jak w pliku tekstowym.

HTML:

<!DOCTYPE html>
<html>
<head>
	<title>Laboratorium 2</title>
	<meta charset="UTF-8">
</head>
<body>
Jakiś tekst
<div id="output"></div>
<div id="output1"></div>
<script>
   ...
</script>
</body>
</html>

JavaScript

function readTextFile(file)
{
    var textFile = new XMLHttpRequest();
    textFile.open("GET", file, false);
    textFile.onreadystatechange = function ()
    {
        if(textFile.readyState === 4)
        {
            if(textFile.status === 200 || textFile.status == 0)
            {
                var content = textFile.responseText;
                console.log(content);
				//document.getElementById('output').innerHTML = content;
				console.log(content.length);
				console.log(content.charAt(0));
				for (i=0; i<87; i++)
				{
					/*if ((content.charAt(i) === 'B') && (content.charAt(i+1) === 'O'))
					{
						console.log(content.charAt(i) + ' ' + content.charAt(i+1));
					}*/
					//if (content.charAt(i)===" ") console.log(content.charAt(i) + ", ");
					//else console.log("nie");
					console.log(content.charAt(i) + ', ');
				}
            }
        }
    }
    textFile.send(null);
}
readTextFile("tekst.txt");

 

Sposób, który próbowałem wykorzystać w pętli, czyli if (content.charAt(i) === " ") console.log(content.charAt(i)); Nie działa. Próbowałem też z różnymi symbolami typu 

/\s/g, czy /^\s*/, ale to również nie pomogło.

Ktoś ma jakiś pomysł?

Wspomniany plik tekstowy ma taką postać:

PRD|AMD|ATHLON|X2|7750|2.6|6|250.00|BOX
PRD|INTEL|i7|X4|720QM|2.8|4|8|450.00|OEM
tekst

3 odpowiedzi

+3 głosów
odpowiedź 18 października 2015 przez Comandeer Guru (600,810 p.)

Zamień \n na <br> i już.

komentarz 20 października 2015 przez ScriptyChris Mędrzec (190,190 p.)

Gdy w pętli wpiszę warunek if (content.charAt(i)== '<br>') console.log(content.charAt(i) + ", "); to ten warunek nie wykonuje się. Dopiero taki warunek: if (content.charAt(i)== '\n') console.log(content.charAt(i) + ", " + '('+i+')'); działa i w konsoli wypisuje mi miejsca, w których nowa linia się pojawia (tzw. "enter").

Tylko, że nie wiem jak to zastosować dla wstawienia nowych linii do div'a 'output' (w pętli for).

document.getElementById('output').innerHTML = content.charAt(i);
if (content.charAt(i)== '\n') document.getElementById('output').innerHTML += '<br>';

Ostatnia instrukcja (+= '<br>') nie działa również dla '\n'.

.

komentarz 20 października 2015 przez furas Maniak (53,800 p.)
edycja 20 października 2015 przez furas

Może weź cały tekst, pozamieniaj co trzeba (pewnie jedna funkcja typu `replace` wystarczy zamiast pętli `for`) i na końcu wstaw całość do output.

wynik = "a\nb\nc".replace(/\n/g, "<br>")

 

0 głosów
odpowiedź 20 października 2015 przez ScriptyChris Mędrzec (190,190 p.)

Częściowo sobie poradziłem

function readTextFile(file)
{
    var textFile = new XMLHttpRequest();
    textFile.open("GET", file, false);
    textFile.onreadystatechange = function ()
    {
        if(textFile.readyState === 4)
        {
            if(textFile.status === 200 || textFile.status == 0)
            {
                var content = textFile.responseText;
                console.log(content);
				
				console.log(content.length);
				console.log(content.charAt(0));
				var lineCounter = 1;
				var word = new Array();
				for (i=0; i<87; i++)
				{
					word[i] = content.charAt(i);
					if (word[i] == '\n')
					{
						lineCounter++;
						word.splice(i, 0, lineCounter + '. ');
					}
				}
				word.unshift("1. ");
				var string = "";
				word.forEach(function(element)
				{
					string += element;
				});
				console.log(string);
            }
        }
    }
    textFile.send(null);
}
readTextFile("tekst.txt");

}

Output:

1. PRD|AMD|ATHLON|X2|7750|2.6|6|250.00|BOX

2. PRD|INTEL|i7|X4|720QM|2.8|4|8|450.00|OEM

3. teks

Tylko mam pytanie - jeśli tworzę tablicę, ale na początku ona jest pusta, to jaki warunek wpisać w pętli for aby iterowała przez całość (bo w trakcie ta tablica będzie uzupełniana)? Warunek i<array.length w momencie gdy jeszcze w tablicy nic nie ma, nie działa (w konsoli pokazuje mi się na szaro "pusty ciąg znaków"). Czy do tego służy pętla forEach?

Zauważyłem, że przy obecnym "ustawieniu" pętli, przy wypisaniu w konsoli tekstu wraz z numeracjąwierszy "zjadło" mi ostatnią literę. Czyli wypadało by jakoś inaczej ustawić warunek końcowy iterowania (albo zmienić pętlę)?

komentarz 20 października 2015 przez furas Maniak (53,800 p.)
edycja 20 października 2015 przez furas

Nie iteruje się po tablicy, do której dodaje się wyniki tylko po danych z który pobiera się rzeczy do przerobienia (aby je potem wstawic do tabeli z wynikami).

---

Może łatwiej będzie podzielić tekst na linie i potem na tym działać

linie = "a\nb\nc".split("\n");

 

0 głosów
odpowiedź 27 października 2015 przez ScriptyChris Mędrzec (190,190 p.)
edycja 28 października 2015 przez ScriptyChris

Jeszcze jedna rzecz. Chcę zrobić kilka if, które będę rozpoznawały czy nastąpiła jedna nowa linia, czy wiele lini, czy jest koniec tekstu. Nie wiem jak zrobić, aby javascript wykrył, czy nastąpiło więcej niż jedna linia odstępu. Jest wyrażenie regexa [^] i ono wykrywa, gdy jest więcej niż jedna linia odstępu (czyli multiliniowy odstęp), ale nie wychodzi mi wykluczenie przy takim ifie aby sprawdzał tylko wiele linii, czyli minimum dwie (bo [^] sprawdza od jednej do kilku).

if (word[i] == '\r' )   //// wykrywa jedną nową linie w tekście
{
   // jakieś działanie
}

else if (word[i] == '[^]')   ////wykrywa od jednej do wielu nowych linii
{
  // jakieś działanie
}

else if (i == word.length) //// Tutaj sobie poradziłem, aby wykrywał przypadek braku nowej linii (czyli koniec tekstu)
{
   // jakieś działanie
}

Problem w tym, że else if (word[i] == '[^]') działa również dla pierwszego przypadku, czego ja nie chcę. Próbowałem doprecyzować te 2 ify poprzez:

if (word[i] == '\r' && word[i] != '[^]')
{
   // ...
}

else if(word[i] == '[^]' && word[i] != '\r')
{
  //...
}

Ale to nie działa. Chodzi mi o to, aby jeśli nastąpi jedna nowa llinia wykonał się pierwszy if, zaś gdy nastąpi więcej niż jedna linia, to ma wykonać się drugi if (tylko, żeby on działał wyłącznie dla minimum 2 linii odstępu). Jak to zrobić :)?

 

komentarz 28 października 2015 przez furas Maniak (53,800 p.)
Koniec linii zwykle oznacza się przez `\n` a nie `\r` więc może dlatego Ci to nie działa
komentarz 28 października 2015 przez furas Maniak (53,800 p.)

Z tego co się orientuje to [^] nie jest poprawnym wyrażeniem regularnym a do tego wydaje mi się, że wyrażenia regularne nie działąją poprzez porównanie == tylko np. 

dane = 'hello \n\n\n world'

/\n{2,}/.test(dane)  

sprawdzenie czy `dane` zawierają dwa lub więcej entery koło siebie

komentarz 28 października 2015 przez furas Maniak (53,800 p.)

Z tego ci się widzę to word[i] oznacza jeden znak w słowie więc porównanie go z dwoma znakami (np. końca linii) nie ma sensu.

komentarz 28 października 2015 przez ScriptyChris Mędrzec (190,190 p.)

Nie działa mi to: /\n{2,}/.test(dane)Jak rozumiem, pod 'dane' podstawiam swoją tablicę, a pod test co?

U mnie nei wszędzie '\n' wykrywa nową linię, stąd użycie '\r' i jak wspomniałem wykrywanie jednej linii działa, a przy [^] wykrywa od jednej do wielu, ale mi chodzi tylko żeby wykrywał od 2 w zwyż.

Faktycznie, porównanie word[i] z kilkoma znakami jest bez sensu :) Tylko, że gdy sprawdzałem dla if (word[i] == '\r' && word[i+1] == '\r' && word[i+2] == '\r'). Tutaj też nieważne czy podstawiałem '\r', czy '\n' wszędzie czy na zmianę - i tak nie działa.

Twoja propozycja może zadziała, tylko nie wiem dokładnie jak jej użyć. Tzn, pod 'dane' podstawić mam swojątablicę, a pod 'test'? if (/\n{2,}/.test(word[i])) console.log("asdfgh"); To oczywiście też nei działa, nawet jeśli wstawię po prostu 'word' bez iteratora, a wiem że wstawienie samej nazwy tablicy wyświetla wszystkie jej elementy, bo nie raz tego używałem.

komentarz 29 października 2015 przez furas Maniak (53,800 p.)

Pod `dane` podstawiam cały napis (a nie tablicę lub pojedyńczy znak), w którym chcę sprawdzić czy są ENTERY.

`test` to nazwa funkcji wbudowana w wyrażenia regularne, do której przekazuję `dane` 

if(/\n{2,}/.test('hello \n\n\n world')) 
    console.log("asdfgh");

---

Różne systemy różnie zapisują ENTER. Linux stosuje tylko '\n', Mac OS tylko '\r' a Windows dwa znaki '\r\n`. Zwykle jednak języki potrafią to rozpoznać i pozwalają stosować tylko '\n'.

---

Z powodu tych dziwnych ENTERÓW zrobiłbym najpierw zamianę '\r\n' na '\n' potem zamianę '\r' na '\n' i miałbym jeden rodzaj ENTERÓW. Potem podzieliłbym tekst na wiersze według '\n". Dla pewności w każdym wierszu usunąłbym skrajne spacje i tabulatory (bo może być pusta linia zawierająca spacje) i wtedy rozpoznawał bym puste linie po długości równej zero 

Samo pozbycie się ENTERÓW o podział na linie
 

linie = "a \n x \r\n q \r y \n b".replace('\r\n', '\n').replace('\r', '\n').split('\n');

 

komentarz 29 października 2015 przez furas Maniak (53,800 p.)
edycja 29 października 2015 przez furas

Taka zamiana lepiej sobie radzi z pojedynczym '\n'

 

linie = "a \n x \r\n q \r \r y \n b".replace(/\r\n|\n/g, '\r').split('\r');

---

EDIT:

 

content = "a \n x \r\n q \r \r y \n b";

// rozbicie na linie
linie = content.replace(/\r\n|\n/g, '\r').split('\r');

// pozbycie sie skrajnych spacji i tabulatorow
for(i=0;i<linie.length;i++){
  linie[i]=linie[i].replace(/^[ \t]*/,'').replace(/[ \t]*$/,'');
}

console.log(linie);
//  ["a", "x", "q", "", "y", "b"] 
// powyżej widać pustą linię między linią `q` i `y` 

 

komentarz 30 października 2015 przez ScriptyChris Mędrzec (190,190 p.)
Dziękuję :-)

Podobne pytania

0 głosów
2 odpowiedzi 256 wizyt
pytanie zadane 30 stycznia 2017 w C i C++ przez czujek22 Dyskutant (7,670 p.)
0 głosów
1 odpowiedź 177 wizyt
pytanie zadane 28 czerwca 2016 w C i C++ przez Munvik Dyskutant (9,350 p.)
–1 głos
1 odpowiedź 255 wizyt
pytanie zadane 29 listopada 2015 w C i C++ przez CodeBlocksCPP Obywatel (1,010 p.)

92,551 zapytań

141,399 odpowiedzi

319,531 komentarzy

61,938 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...