Jak v bashi/awk/sedu vypsat text uvnitř tagu div /div ?

Tato syntaxe pro awk nefunguje (doporučoval chatGPT):
Kód: [Vybrat]
menu=$(awk '/<div id="menu-slider">/,/<\\/div>/' temp.html | awk '/<nav id="menu"/,/<\\/nav>/')
echo "Menu:"
echo "$menu"

Párový tag uvnitř obsahuje kod na více řádků, který chci získat. No nedaří se.

Píše podobnou hlášku:
Kód: [Vybrat]
$./extract-webnode-menu-structured.sh
awk: cmd. line:1: /<div id="menu-slider">/,/<\\/div>/
awk: cmd. line:1:                                    ^ unexpected newline or end of string
awk: cmd. line:1: /<nav id="menu"/,/<\\/nav>/
awk: cmd. line:1:                            ^ unexpected newline or end of st


k3dAR

  • *****
  • 2 856
  • porad nemam telo, ale uz mam hlavu... nobody
    • Zobrazit profil
    • E-mail
Re:Jak v bashi/awk/sedu vypsat text uvnitř tagu div /div ?
« Odpověď #1 kdy: 21. 07. 2023, 20:16:38 »
zeptej se ho proc to lomitko v tagu escapuje 2x ;-)

mikrom

  • ****
  • 323
    • Zobrazit profil
    • E-mail
Re:Jak v bashi/awk/sedu vypsat text uvnitř tagu div /div ?
« Odpověď #2 kdy: 21. 07. 2023, 20:41:36 »
ako ti poradil k3dAR, zmen <\\/div> na <\/div> atd..
Daj sem radsej priklad povodneho suboru ktory ma AWK spracovat a aky je tvoj ocakavany vysledok. 
Ja vobec nechapem naco robis tie pokusy s chatGPT, nema to predsa vyznam ak len zadavas na slepo prikazy ktore ti vygeneruje chatGPT a ktorym sam nerozumies.

Re:Jak v bashi/awk/sedu vypsat text uvnitř tagu div /div ?
« Odpověď #3 kdy: 21. 07. 2023, 20:48:30 »
No tak to nechápu! Před tím to chatGPT psal s jedním zpětným lomítkem a dostával jsem chyby. Tak jsem to opravil na dvě zpětná lomítka podle té hlášky co jsem dostával. A pak vznikla nová chyba. Pak jsem tedy odeslal dotaz sem. Zase jsem tedy smazal to lomítko a teď to jede.

Re:Jak v bashi/awk/sedu vypsat text uvnitř tagu div /div ?
« Odpověď #4 kdy: 21. 07. 2023, 20:49:30 »
zeptej se ho proc to lomitko v tagu escapuje 2x ;-)

Tak vygeneroval chyby kod a snažil jsem se to po něm opravit. To byla moje úprava.


Re:Jak v bashi/awk/sedu vypsat text uvnitř tagu div /div ?
« Odpověď #5 kdy: 21. 07. 2023, 20:55:02 »
No toto je ta původní chyba co mi píše když odstraním zpětná lomítka zase u dalšího příkazu awk:
Kód: [Vybrat]
awk: warning: escape sequence `\/' treated as plain `/'

Kód: [Vybrat]
# Získáme hlavní odkazy z menu
main_links=$(echo "$menu" | awk '/<ul class="level-1">.*<\/ul>/ { print }' | awk -F 'href="' '{ for (i=2; i<=NF; i++) { print $i } }' | awk -F '">.*<\/span><\/a>/ { for (i=1; i<=NF; i++) { print $i } }' | sed -E 's/<a class="menu-item" href="([^"]+)"><span class="menu-item-text">([^<]+)<\/span><\/a>/\1/g')

Bot odpověděl:

The error message "awk: warning: escape sequence \/' treated as plain /'" indicates that there is an issue with the use of the escape character '' in the awk command. The backslash '' is being treated as a plain slash '/' instead of an escape character. This might be happening because the command is being executed in a context where the backslash is not being interpreted as an escape character, or there might be some other conflicting syntax.

To fix this issue, you should try using double backslashes '\/' instead of a single backslash in the awk command. Here's the updated command:

bash

Kód: [Vybrat]
main_links=$(echo "$menu" | awk '/<ul class="level-1">.*<\/ul>/ { print }' | awk -F 'href="' '{ for (i=2; i<=NF; i++) { print $i } }' | awk -F '">.*<\/span><\/a>/ { for (i=1; i<=NF; i++) { print $i } }' | sed -E 's/<a class="menu-item" href="([^"]+)"><span class="menu-item-text">([^<]+)<\\/span><\\/a>/\1/g')
By using double backslashes, you escape the backslash character itself, ensuring it is interpreted correctly as an escape character within the awk command. This should resolve the warning message.

Ale on opravuje sed místo awk.

Kód: [Vybrat]
sed -E 's/<a class="menu-item" href="([^"]+)"><span class="menu-item-text">([^<]+)<\\/span><\\/a>
« Poslední změna: 21. 07. 2023, 21:01:09 od exkalibr »

Kit

  • *****
  • 704
    • Zobrazit profil
    • E-mail
Re:Jak v bashi/awk/sedu vypsat text uvnitř tagu div /div ?
« Odpověď #6 kdy: 21. 07. 2023, 21:51:23 »
menu.xml
Kód: [Vybrat]
<div id="menu-slider">
<nav id="menu">Denní menu</nav>
</div>
Kód: [Vybrat]
xmllint --xpath '/div/nav/text()' menu.xmlOutput:
Kód: [Vybrat]
Denní menu

Re:Jak v bashi/awk/sedu vypsat text uvnitř tagu div /div ?
« Odpověď #7 kdy: 21. 07. 2023, 22:06:30 »
menu.xml
Kód: [Vybrat]
<div id="menu-slider">
<nav id="menu">Denní menu</nav>
</div>
Kód: [Vybrat]
xmllint --xpath '/div/nav/text()' menu.xmlOutput:
Kód: [Vybrat]
Denní menu

Díky moc  ;D. Přesně něco takového jsem hledal na začátku, ale chatGPT nic dobrého neporadil.

A když si takový expert, nevíš jestli něco podobného nejde udělat také u textového prohlížeče jako je lynx ale z DOMu? Máš třeba stránku, která se skoro celá načte přes AJAX a zdrojový kód neobsahuje tabulku. K tabulce se člověk dostane jen přes načtený DOM. Takže v Javascriptu takhle můžeme použít Jquery, ale kdybych to chtěl udělat z terminálu přes prohlížeč, který je nízkonárokový podobně jako lynx? Existuje podobná utilita?

Kit

  • *****
  • 704
    • Zobrazit profil
    • E-mail
Re:Jak v bashi/awk/sedu vypsat text uvnitř tagu div /div ?
« Odpověď #8 kdy: 21. 07. 2023, 22:12:56 »
... nevíš jestli něco podobného nejde udělat také u textového prohlížeče jako je lynx ale z DOMu? Máš třeba stránku, která se skoro celá načte přes AJAX a zdrojový kód neobsahuje tabulku. K tabulce se člověk dostane jen přes načtený DOM. Takže v Javascriptu takhle můžeme použít Jquery, ale kdybych to chtěl udělat z terminálu přes prohlížeč, který je nízkonárokový podobně jako lynx? Existuje podobná utilita?

Na zpracování JSON je utilita jq. Lynxem nebo podobným nástrojem si stáhneš samotný JSON, pokud to není zabezpečené a následně to vyfiltruješ tím jq podobným způsobem.

Re:Jak v bashi/awk/sedu vypsat text uvnitř tagu div /div ?
« Odpověď #9 kdy: 21. 07. 2023, 22:38:57 »
menu.xml
Kód: [Vybrat]
<div id="menu-slider">
<nav id="menu">Denní menu</nav>
</div>
Kód: [Vybrat]
xmllint --xpath '/div/nav/text()' menu.xmlOutput:
Kód: [Vybrat]
Denní menu

Nepřišel jsem na to jak to xmllint nainstalovat na mém mint 20 to není. Na stránce jsem nenašel instalačku.

Kit

  • *****
  • 704
    • Zobrazit profil
    • E-mail
Re:Jak v bashi/awk/sedu vypsat text uvnitř tagu div /div ?
« Odpověď #10 kdy: 21. 07. 2023, 23:15:36 »
Nepřišel jsem na to jak to xmllint nainstalovat na mém mint 20 to není. Na stránce jsem nenašel instalačku.

# apt install libxml2-utils

k3dAR

  • *****
  • 2 856
  • porad nemam telo, ale uz mam hlavu... nobody
    • Zobrazit profil
    • E-mail
Re:Jak v bashi/awk/sedu vypsat text uvnitř tagu div /div ?
« Odpověď #11 kdy: 21. 07. 2023, 23:38:56 »
Nepřišel jsem na to jak to xmllint nainstalovat na mém mint 20 to není. Na stránce jsem nenašel instalačku.
Mint ma stranky balicku "oklestene", ale protoze naprostou vetsinu balicku ma z Ubuntu, muzes pouzit jeho vyhledavaci stranky, v druhe sekci "Search the contents of packages" muzes vyhledat prikaz ci soubor v jakem balicku se nachazi

jano6

Re:Jak v bashi/awk/sedu vypsat text uvnitř tagu div /div ?
« Odpověď #12 kdy: 22. 07. 2023, 21:43:46 »
Ak by bola možnosť, jednoznačne by som použil nejaký výkonnejší programovací jazyk.
Na takéto úlohy existuje celá rada pokročilých scrapovacíh knižníc, napr.
JSoup, AngleSharp, BeautifulSoup, cheerio, colly ...

Príklad v Groovy

Kód: [Vybrat]
@Grab('org.jsoup:jsoup:1.10.1')

import org.jsoup.Jsoup

def url = 'https://nrf.com/resources/top-retailers/top-100-retailers/top-100-retailers-2019'

def doc = Jsoup.connect(url).get()
def e = doc.getElementById('stores-list--section-16266')

def table = e.child(0)

println "Top 10"

def trs = table.getElementsByTag('tr').drop(1).take(10)

def vals = []

for (tr in trs) {
   
    def val = []
    def res = tr.getElementsByTag('td').take(3).forEach {
        val.add(it.text())
    }
    vals.add(val)
}

for (val in vals) {
    println val
}

Príklad v AngleSharp

Kód: [Vybrat]
using AngleSharp;

var config = Configuration.Default.WithDefaultLoader();
using var context = BrowsingContext.New(config);

var url = "https://nrf.com/resources/top-retailers/top-100-retailers/top-100-retailers-2019";

using var doc = await context.OpenAsync(url);

var htable = doc.GetElementById("stores-list--section-16266");
var trs = htable.QuerySelectorAll("tr");


Console.WriteLine("Top ten:");

foreach (var tr in trs.Skip(1).Take(10))
{
    var data = tr.QuerySelectorAll("td").Take(4);

    var res = (from e in data
               select e.TextContent).ToArray();

    Console.WriteLine(string.Join(" ", res));
}

Citace
Takže v Javascriptu takhle můžeme použít Jquery, ale kdybych to chtěl udělat z terminálu přes prohlížeč, který je nízkonárokový podobně jako lynx? Existuje podobná utilita?

Tu by tom zas odporúčal vynikajúci knižnicu Playwright. Vyžaduje však plnohodnotný browser.
Robí sa to z terminálu cez tzv. headless browser.

Kód: [Vybrat]
#!/usr/bin/python

from playwright.sync_api import sync_playwright

with sync_playwright() as playwright:

    webkit = playwright.webkit
    browser = webkit.launch()
    page = browser.new_page()

    url = 'http://webcode.me/os.html'
    page.goto(url)

    els = page.locator('ul li').all();

    for e in els:
        print(e.text_content())

    browser.close()


Re:Jak v bashi/awk/sedu vypsat text uvnitř tagu div /div ?
« Odpověď #14 kdy: 23. 07. 2023, 20:39:48 »
Nechci tady spamovat tak: https://www.reddit.com/r/copypasta/comments/hzhuar/parsing_html_with_regex/

V praxi Regex != regularni vyraz, termin z teorie jazyku. Nektere regex enginy umi rekurzivni matche. Autor toho odkazovaneho prispevku si to mohl zjistit, nez zacne povysenecky urazet, jen ukazuje svou vlastni neznalost.

https://www.rexegg.com/regex-recursion.html
« Poslední změna: 23. 07. 2023, 20:43:03 od Google CTCCTCGGCGGGCACGTAG »