Ubuntu Suomen keskustelualueet

Ubuntun käyttö => Ohjelmointi, palvelimet ja muu edistyneempi käyttö => Aiheen aloitti: JA5U - 27.04.16 - klo:15.42

Otsikko: [Ratkaistu] viimeinkin: Tekstitiedostojen rakenteistaminen / soveltuva skripti
Kirjoitti: JA5U - 27.04.16 - klo:15.42
Moi

Nyt olis 1000 tekstitiedostoa, jotka pitäisi saada tietokantaan.

Tekstitiedostot ovat jokseenkin rakenteisessa muodossa:
-tunniste ja data samalla rivillä esim: kuvaus;lorem ipsum dolor sit amet
-osassa erotin on = ja osassa pelkkä \s
-pääsääntöisesti data on tekstiä ja numeroita ja osin pvm jne (ohjelmoinin/konekielisen käsittelyn näkökulmsta vahvasti tyypitettyjä?)
-rivien määrä per tiedosto vaihtelee
-kaikilla on kuitenkin yhteiset tunnisteet

Kerkesin jos melko paljon muokkaamaan näitä eli
-kaikilla on sama erotin ;,
-tyhjät rivit on poistettu,
-osa datasta on rakenteistettu omille riveille jne.

Voisin tietysti jatkon kannalta yhdistää käytetyt komennot yhdeksi skriptiksi, mutta kiinnoistaisi tietää, jos tällaiseen tarkoitukseen on olemassa jotain työkaluja?
Kenties ihan graafisellä käyttöliittymällä varustettuja...
Omilla avainsanoilla en löytänyt kovinkaan osuvia.
Otsikko: Vs: Tekstitiedostojen analysointi ja rakenteistaminen / siihen soveltuva skripti
Kirjoitti: nm - 27.04.16 - klo:16.05
Skripteillähän tuollaiset muunnokset tehdään. Esikäsittelyn voi usein tehdä vaikka shell-skriptillä, joka kutsuu grep, sed tai awk -ohjelmia tarpeen mukaan. Tai sitten suoraan Pythonilla tai jollain muulla vastaavalla nopeaan kehitykseen soveltuvalla kielellä, jossa on tarvittavat välineet ja tietokantarajapinnat.

Graafista käyttöliittymää en itse ole tällaisissa hommissa kaivannut. Ehkä sitten, jos muunnos on automatisoitavissa vain osittain ja vaatisi tiedostokohtaista säätämistä. (Hankalia ovat esim. raporttidokkarit, joista pitäisi poimia vapaasta tekstistä asioita.)
Otsikko: Vs: Tekstitiedostojen analysointi ja rakenteistaminen / siihen soveltuva skripti
Kirjoitti: JA5U - 27.04.16 - klo:17.13
Em. muutokset tein tosiaan sedillä ja eikä ollut edes hirvittävän vmäistä.
Tarkemmin ottaen
Koodia: [Valitse]
find . -type f -exec sed -i 's/pois/tilalle/g' {} \;^M oli uusi juttu, mutta senkin sai korvattua, kun käytti \r...

Vissiin otan pisimmästä tiedostosta eli eniten rivejä sisältävästä tarvittavat sarakenimet kantaan varten.
Sen jälkeen voi loopata tiedostot läpi ja muodostaa niistä insert lausekkeet...kai...
Otsikko: Vs: Tekstitiedostojen analysointi ja rakenteistaminen / siihen soveltuva skripti
Kirjoitti: JA5U - 28.04.16 - klo:00.03
Milläs saisin nyt poistettu useamman samanlaisen mjonon samalta riviltä?
Esim.
Teksti;01.01.2001Teksti;01.01.2001Teksti;01.01.2001Teksti;01.01.2001Teksti;01.01.2001

Siten, että ensimmäinen kuitenkin säilyy...
Otsikko: Vs: Tekstitiedostojen analysointi ja rakenteistaminen / siihen soveltuva skripti
Kirjoitti: nm - 28.04.16 - klo:00.53
Jotain tällaista voi kokeilla:

Koodia: [Valitse]
sed -r 's/^(.+)(\1)+$/\1/' input.txt
Vaatii, että merkkijono toistuu täsmälleen samanlaisena, eikä rivillä ole mitään muuta. Jos siellä on yksikin poikkeava merkki, riville ei tehdä mitään. Lisäksi esimerkiksi rivi aaaa muuttuu a:ksi.
Otsikko: Vs: Tekstitiedostojen analysointi ja rakenteistaminen / siihen soveltuva skripti
Kirjoitti: JA5U - 28.04.16 - klo:08.46
Jotain tällaista voi kokeilla:

Koodia: [Valitse]
sed -r 's/^(.+)(\1)+$/\1/' input.txt
Vaatii, että merkkijono toistuu täsmälleen samanlaisena, eikä rivillä ole mitään muuta. Jos siellä on yksikin poikkeava merkki, riville ei tehdä mitään. Lisäksi esimerkiksi rivi aaaa muuttuu a:ksi.

Täytyypä illalla kokeilla.

Eilen tein omia kokeliuja, mutta tuloksetta. Tuota edelläkin käytettyä '\1' kokeilin korvausarvona, mutta se aiheutti jonkin herjan.
Tuohan on käsittäkseni viittaus 'capturing groupin' eli sillä saadaan se 1. osuma talteen?
Tämäkin syntaksi on hieman erilainen kuin muissa yhteyksissä.

En saanut myöskään noita sulkumerkkejä toimimaan () - kokeilin kenoviivan kanssa ja ilman.

En tiedä, että onko joku versio juttu, mutta itselläni on 15.04 asennettuna
Otsikko: Vs: Tekstitiedostojen analysointi ja rakenteistaminen / siihen soveltuva skripti
Kirjoitti: nm - 28.04.16 - klo:10.14
Eilen tein omia kokeliuja, mutta tuloksetta. Tuota edelläkin käytettyä '\1' kokeilin korvausarvona, mutta se aiheutti jonkin herjan.

Varmaan ne sulut olivat jotenkin pielessä. Sedin perustilassa ryhmittelysulut pitää tosiaan suojata kenoviivalla.

Lisäksi tässä on kätevää käyttää \{1,\}:n sijaan +:aa, jota sed tukee vain -r -parametrin kautta valittavassa laajennetussa tilassa. Tällöin myöskään sulkuja ei tarvitse suojata. Perustilassa lauseke pitäisi kirjoittaa näin:

Koodia: [Valitse]
sed 's/^\(.\{1,\}\)\(\1\)\{1,\}$/\1/' input.txt

Lisäys:
Huomasin säännöllisten lausekkeiden ahneesta sovituksesta (greedy matching) johtuvan ongelman. Jos merkkijono toistuu parillisen määrän kertoja, tämä lauseke tunnistaa sen koostuvan vain kahdesta osasta, koska peräkkäin asetettuna ne muodostavat alkuperäisen merkkijonon.

5 toistoa:
Koodia: [Valitse]
$ echo "aaaaa" |  sed -r 's/^(.+)(\1)+$/\1/'
a

6 toistoa:
Koodia: [Valitse]
$ echo "aaaaaa" |  sed -r 's/^(.+)(\1)+$/\1/'
aaa

Tätä voi olla vaikea ratkaista sedillä toistamatta operaatiota useita kertoja: esimerkiksi ajamalla komentoa silmukassa, kunnes tulos ei enää muutu syötteeseen verrattuna.

Perlillä voi käyttää non-greedy-sovitusta (http://docstore.mik.ua/orelly/perl/cookbook/ch06_16.htm): (.+?)

Koodia: [Valitse]
$echo "aaaaaa" | perl -pe 's/^(.+?)(\1)+$/\1/'
a
Otsikko: Vs: Tekstitiedostojen analysointi ja rakenteistaminen / siihen soveltuva skripti
Kirjoitti: JA5U - 28.04.16 - klo:20.25
Herjaa pukkaa:
Koodia: [Valitse]
# find . -type f -name "*.txt" -exec sed -ir 's/^([a-z]+\s+[a-z]+;)(\d{2}).(\d{2}).(\d{4}) (\d{2}):(\d{2}):(\d{2})(\1)+$/\1/ig' {} \;
sed: -e expression #1, char 88: Invalid back reference

Tässä siis täsmää "Sana sana;dd.mm.yyyy hh:mm:ss".
Otsikko: Vs: Tekstitiedostojen analysointi ja rakenteistaminen / siihen soveltuva skripti
Kirjoitti: JA5U - 28.04.16 - klo:21.59
Kun ei se sujunut, niin kylmästi katkaisin viimeisen rivin X merkkimäärän kohdalta.
Tämä siis nappaa viimeisen rivin 36 merkkiä ja korvaa koko rivin niillä merkeillä.
Koodia: [Valitse]
find . -type f -name "*.txt" -exec sed -i -r '$ s/(.){36}/\1/ig' {} \;
Otsikko: Vs: Tekstitiedostojen analysointi ja rakenteistaminen / siihen soveltuva skripti
Kirjoitti: nm - 29.04.16 - klo:01.12
Herjaa pukkaa:
Koodia: [Valitse]
# find . -type f -name "*.txt" -exec sed -ir 's/^([a-z]+\s+[a-z]+;)(\d{2}).(\d{2}).(\d{4}) (\d{2}):(\d{2}):(\d{2})(\1)+$/\1/ig' {} \;
sed: -e expression #1, char 88: Invalid back reference

Tässä siis täsmää "Sana sana;dd.mm.yyyy hh:mm:ss".

Virhe johtui tästä:

Koodia: [Valitse]
sed --help
Lainaus
-i[SUFFIX], --in-place[=SUFFIX]
                 edit files in place (makes backup if SUFFIX supplied)

Eli sed tulkitsee parametrin "-ir" parametriksi "-i", jolla on määreenä väliaikaistiedoston päätteenä käytettävä merkkijono "r". Parametri -r ei siis mene perille ja säännöllisen lausekkeen syntaksi ei kelpaa. Komento on kirjoitettava, kuten myöhemmässä skriptissäsi teit: "sed -i -r"


Ongelma 2

Sed ei tulkitse \d:tä numeroksi. Käytä sen sijaan syntaksia [0-9] tai merkkiluokkaa [[:digit:]]
Myös \s on vähän epävarma, jos skriptin pitäisi olla siirrettävissä muihin järjestelmiin. Vain GNU sed tukee sitä. [[:space:]] on laajemmin tuettu.

Perl tukee \d:tä ja \s:ää.


Ongelma 3

Skripti ei ratkaise esitettyä tehtävää. Olkoon toistuva merkkijono esimerkiksi "yks kaks;28.04.2016 10:11:22":

Koodia: [Valitse]
echo "yks kaks;28.04.2016 10:11:22yks kaks;28.04.2016 10:11:22" | sed -r 's/^([a-z]+[[:space:]]+[a-z]+;)([0-9]{2}).([0-9]{2}).([0-9]{4}) ([0-9]{2}):([0-9]{2}):([0-9]{2})(\1)+$/\1/ig'Tulos:
Koodia: [Valitse]
yks kaks;28.04.2016 10:11:22yks kaks;28.04.2016 10:11:22
Ulos saatiin syötetty merkkijono, eli lauseke ei tunnistanut toistoa. Sen sijaan skripti osaa tehdä tällaisen muunnoksen:

"yks kaks;28.04.2016 10:11:22yks kaks;" --> "yks kaks;"

Tai:

"yks kaks;28.04.2016 10:11:22yks kaks;yks kaks;yks kaks;" --> "yks kaks;"


Alkuperäinen ongelma ratkeaa tällaisella lausekkeella, jos siis halutaan speksata toistuvan merkkijonon hyväksytty sisältö tarkasti:

Koodia: [Valitse]
sed -i -r 's/^([a-z]+[[:space:]]+[a-z]+;[0-9]{2}.[0-9]{2}.[0-9]{4} [0-9]{2}:[0-9]{2}:[0-9]{2})(\1)+$/\1/' input.txt
Tässä on poistettu ylimääräiset sulut numerokenttien ympäriltä ja siirretty päivämäärä ja aika toistuvan ryhmän sisään.

PS. Kuten mitä tahansa ei-triviaalia koodia, säännöllisiä lausekkeita kannattaa testata aluksi yksittäisillä syötteillä sen sijaan, että ajaa koko datasetin skriptin läpi. Lausekkeita joutuu aina viilaamaan jonkin verran ja testailemaan rajatapauksia. Yleensä on helpointa vain putkittaa testattava syöte skriptille komentorivillä. Lähdetiedostojen muuttamista (sed -i) on syytä välttää kehityksen aikana, ja ehkä muutenkin.
Otsikko: Vs: Tekstitiedostojen analysointi ja rakenteistaminen / siihen soveltuva skripti
Kirjoitti: JA5U - 29.04.16 - klo:08.44

Ongelma 2

Sed ei tulkitse \d:tä numeroksi. Käytä sen sijaan syntaksia [0-9] tai merkkiluokkaa [[:digit:]]
Myös \s on vähän epävarma, jos skriptin pitäisi olla siirrettävissä muihin järjestelmiin. Vain GNU sed tukee sitä. [[:space:]] on laajemmin tuettu.

Perl tukee \d:tä ja \s:ää.

Hmh...

Ongelma 3
Alkuperäinen ongelma ratkeaa tällaisella lausekkeella, jos siis halutaan speksata toistuvan merkkijonon hyväksytty sisältö tarkasti:

Koodia: [Valitse]
sed -i -r 's/^([a-z]+[[:space:]]+[a-z]+;[0-9]{2}.[0-9]{2}.[0-9]{4} [0-9]{2}:[0-9]{2}:[0-9]{2})(\1)+$/\1/' input.txt
Tässä on poistettu ylimääräiset sulut numerokenttien ympäriltä ja siirretty päivämäärä ja aika toistuvan ryhmän sisään.

Näinhän se tosiaan toimii. Unohdin tarkentaa, että nuo mahdolliset toistot sisältävät eri ajan eli eivät täsmää \1.

Kuitenkin tuo viimeisen rivin muokkaus oli toimiva temppu tässä tapauksessa, kun ne olivat aina viimeisellä rivillä.
Olisi pitänyt heti alussa muokata kaikista tiedostoista tuo "Sana sana" -> "sana". Ei se hirveästi selkeytä tarvittavaa lauseketta, mutta kuitenkin...

http://www-rohan.sdsu.edu/doc/sed.html
Otsikko: Vs: Tekstitiedostojen analysointi ja rakenteistaminen / siihen soveltuva skripti
Kirjoitti: JA5U - 03.05.16 - klo:13.09
Nyt tarttis saada poistettu tietyiltä riveiltä ;-merkin jälkeen kaikki muut merkit paitsi numerot ja väliviiva?
esim "rivintunniste; noin. 10-15" -> "rivintunniste;10-15"

En tiedä, että onko sed tähän paras vai joku muu?

Sitten, kun tiedostot on kunnossa, niin ne pitäisi saada myös käännetty riveiltä sarakkeisiin.
Tuommosta https://sourceforge.net/projects/transpose/ ehdoteltiin jossain, mutta en saanut sitä toimimaan.

EDIT: Nyt sain toimimaan, kun löysin yhdestä ketjusta ohjeet, että kuinka sitä käytetään:
Koodia: [Valitse]
transpose -t --fsep ";" input.txt > output.txtTosin, tulokset olivat sinne päin eli tiedostosta muodostui kolmirivinen kahden sijaan, jossa on muutamia otsakkeita sikinsokin.

Toinen minkä löysin gnu datamash, mutta se taas kaatui
Koodia: [Valitse]
datamash: transpose input error: line 4 has 2 fields (previous lines had 3);
Johtuuko sitten ääkkösistä? Hieman menee iteroiden, pitääkin käyttää lisää valitsimia
Koodia: [Valitse]
--no-strict -filler 0Joka tosin kaatuu:
Koodia: [Valitse]
datamash: malloc.c:3096: sYSMALLOc: Assertion `(old_top == (((mbinptr) (((char *) &((av)->bins[((1) - 1) * 2])) - __builtin_offsetof (struct malloc_chunk, fd)))) && old_size == 0) || ((unsigned long) (old_size) >= (unsigned long)((((__builtin_offsetof (struct malloc_chunk, fd_nextsize))+((2 * (sizeof(size_t))) - 1)) & ~((2 * (sizeof(size_t))) - 1))) && ((old_top)->size & 0x1) && ((unsigned long)old_end & pagemask) == 0)' failed.
Aborted (core dumped)
Otsikko: Vs: Tekstitiedostojen analysointi ja rakenteistaminen / siihen soveltuva skripti
Kirjoitti: nm - 04.05.16 - klo:01.18
Sitten, kun tiedostot on kunnossa, niin ne pitäisi saada myös käännetty riveiltä sarakkeisiin.
Tuommosta https://sourceforge.net/projects/transpose/ ehdoteltiin jossain, mutta en saanut sitä toimimaan.

EDIT: Nyt sain toimimaan, kun löysin yhdestä ketjusta ohjeet, että kuinka sitä käytetään:
Koodia: [Valitse]
transpose -t --fsep ";" input.txt > output.txtTosin, tulokset olivat sinne päin eli tiedostosta muodostui kolmirivinen kahden sijaan, jossa on muutamia otsakkeita sikinsokin.

Esiintyykö erotin ";" jokaisella rivillä kerran ja vain kerran? Muutenhan sarakkeita on eri määrä eri riveillä ja transpose varmaankin sekoaa siihen.

Kyhäsin huvikseni shell-skriptin samaan hommaan, vaikka helpommin kyllä onnistuisi jollain kehittyneemmällä kielellä.

Koodia: [Valitse]
#!/bin/sh

if [ $# -lt 1 ]; then
    echo "Transpose delimited data"
    echo ""
    echo "usage: $0 input.txt > output.txt"
    echo ""
    exit
fi

input="$1"

delimiter=";"
substitute=","

printrow() {
    outdelim=""
    echo "$1" | while IFS= read -r val; do
        echo -n "$outdelim$val"
        outdelim="$delimiter"
    done
}

# Regular expression to match two columns separated by $delimiter
matchcolumns="^\([^$delimiter]*\)$delimiter\(.*\)$"

# Pick first column
header=$(sed -e "s/$matchcolumns/\1/" "$input")

# Pick rest of the  columns. They are all treated as one combined column.
data0=$(sed -e "s/$matchcolumns/\2/" "$input")

# Substitute leftover delimiters with $substitute to avoid mismatching pairs
data=$(echo "$data0" | tr "$delimiter" "$substitute")

printrow "$header"
echo ""
printrow "$data"
echo ""


Nyt tarttis saada poistettu tietyiltä riveiltä ;-merkin jälkeen kaikki muut merkit paitsi numerot ja väliviiva?
esim "rivintunniste; noin. 10-15" -> "rivintunniste;10-15"

En tiedä, että onko sed tähän paras vai joku muu?

Taitaa mennä aika vaikeaksi pelkällä sedillä. Awk:lla onnistunee helpommin. Tässä shell+sed -ratkaisu sovellettuna yllä esitetystä:

Koodia: [Valitse]
inputfile="$1"

delimiter=";"

# Remove stuff from the second column. This expression keeps numbers 0-9 and the dash character and removes everything else.
removethis="[^0-9-]"

matchcolumns="^\([^$delimiter]*\)$delimiter\(.*\)$"

cat "$inputfile" | while IFS= read -r val; do
    header=$(echo "$val" | sed -e "s/$matchcolumns/\1/")
    data=$(echo "$val" | sed -e "s/$matchcolumns/\2/; s/$removethis//g")
    echo "$header$delimiter$data"
done
Otsikko: Vs: Tekstitiedostojen analysointi ja rakenteistaminen / siihen soveltuva skripti
Kirjoitti: JA5U - 04.05.16 - klo:10.40
Tästähän alkaa paisua jo aika hc ketju.
Pitääpä laittaa illalla testaten noita.

Esiintyykö erotin ";" jokaisella rivillä kerran ja vain kerran? Muutenhan sarakkeita on eri määrä eri riveillä ja transpose varmaankin sekoaa siihen.

Kyllä, valitsin tuon merkin erottimeksi siksi, että sitä ei esiintynyt tekstissä muutoin.
Eilen kävi ilmi, että ilmeisesti tuo datamash sekosi siitä syystä, että kyseisellä rivillä tunniste-arvoparilta puuttui arvo: "tunniste;".
--no-strict ilmeisesti estää sen kaatumisen, mutta sitä käyttämällä tuli taas tuo aiemmin ilmoitettu virhe, joka laukaisi myös Ubuntun oman virheilmoituksen...

Kokeilin myös vaihtaa rajoitinmerkiksi :, mutta "tulokset" olivat siitä huolimatta vastaavanlaisia.
Tuolla ;-merkillä se itseasiassa katkaisi koko komennon, jos sitä käytti ohjeiden tapaan -t; ilman hipsuja.
Otsikko: Vs: Tekstitiedostojen analysointi ja rakenteistaminen / siihen soveltuva skripti
Kirjoitti: JA5U - 05.05.16 - klo:16.10
Menee kyllä vähä ylihilseen nuo aiemmat skriptit.
Johtuu siitä, etten tunne tuota syntaksia, erikoismerkkejä taikka muuttujien "käsittelyä".

Loogisesti ajateltuna tässä on melko yksinkertaisesti ongelmasta kyse:
luetaan rivi,
jaetaan se kahteen osaan ;-merkin perustella,
1. osa menee 1. rivin jatkoksi ja
2. osa 2. rivin jatkoksi.

Jotenkin tätä pähkäilin ja rupesin miettimään sedittämistä siten, että suoritetaan useampi komento
Koodia: [Valitse]
sed -e '' -e ''
En kuitenkaan ymmärrä, että miten tuon ensimmäisen sed komennon tulokset saisi siirretty seuraavalle, joka taas muokkaisi tiettyä tiedostoa edellä kuvatun mukaisesti.
Tai ts. miten \1 ja \2 saisi siirrettyä eteenpäin sedille/bashille käsiteltäväksi, joka sitten suorittaisi \1 lisäyksen riville 1 ja \2 lisäyksen riville 2 tiettyyn tiedostoon?

Eli
Koodia: [Valitse]
halkaise;minut
halkaiset;minutkin
...
tulee
Koodia: [Valitse]
halkaise,halkaiset
minut,minutkin
...

Pseudo
load input
while read line
split line to array
open output
write ','+array[1] to output line 1
write ','+array[2] to output line 2
Otsikko: Vs: Tekstitiedostojen analysointi ja rakenteistaminen / siihen soveltuva skripti
Kirjoitti: nm - 07.05.16 - klo:02.26
Menee kyllä vähä ylihilseen nuo aiemmat skriptit.
Johtuu siitä, etten tunne tuota syntaksia, erikoismerkkejä taikka muuttujien "käsittelyä".

Oliko skriptin käytössä tai toiminnassa jokin ongelma? Ei pitäisi olla tarvetta muokata sitä mitenkään, jos tarkoituksena on erottaa ;-merkillä erotetut kaksi saraketta ja kirjoittaa arvot ;-merkillä erotettuina kahdelle riville. Tekee saman kuin transpose, mutta pitäisi toimia lähes kaikilla kuviteltavissa olevilla syötteillä.

Loogisesti ajateltuna tässä on melko yksinkertaisesti ongelmasta kyse:
luetaan rivi,
jaetaan se kahteen osaan ;-merkin perustella,
1. osa menee 1. rivin jatkoksi ja
2. osa 2. rivin jatkoksi.

Skriptini käyttää osien erotteluun säännöllistä lauseketta "^\([^;]*\);\(.*\)$"
Ensimmäisen sarakkeen kaikki arvot saadaan siis rivinvaihdoin eroteltuna komennolla:
Koodia: [Valitse]
sed -e "s/^\([^;]*\);\(.*\)$/\1/" tiedosto.txt
Toisen sarakkeen arvot saadaan vastaavasti komennolla:
Koodia: [Valitse]
sed -e "s/^\([^;]*\);\(.*\)$/\2/" tiedosto.txt
Nämä tallennetaan muuttujiin (ensimmäinen sarake muuttujaan header ja toinen sarake muuttujaan data0. Skriptin printrow-funktio muuntaa rivinvaihdot ;-välimerkeiksi ja tulostaa rivit stdoutiin, jonka voit ohjata haluamaasi tiedostoon.
Otsikko: Vs: Tekstitiedostojen analysointi ja rakenteistaminen / siihen soveltuva skripti
Kirjoitti: JA5U - 09.05.16 - klo:11.35
Eipä näissä koodeissa liene vikaa, pikemminkin lukijassa.

Vkloppuna ajelin näitä ja CSVhen tuli kolme riviä.
En oikein tiedä, että mistä se johtuu, kun sama tapahtui muillakin ratkaisulla.

Jotenkin tuntuu, että tiedostoissa olisi jotain mätää, mutta ei ainakaan näytä olevan.
Otsikko: Vs: Tekstitiedostojen analysointi ja rakenteistaminen / siihen soveltuva skripti
Kirjoitti: nm - 10.05.16 - klo:03.15
Eipä näissä koodeissa liene vikaa, pikemminkin lukijassa.

Vkloppuna ajelin näitä ja CSVhen tuli kolme riviä.
En oikein tiedä, että mistä se johtuu, kun sama tapahtui muillakin ratkaisulla.

Jotenkin tuntuu, että tiedostoissa olisi jotain mätää, mutta ei ainakaan näytä olevan.

Sitten tarvittaisiin esimerkki, jossa näin tapahtuu. En oikein näe, miten se olisi mahdollista, koska skripti tulostaa vain kaksi riviä, eikä riveille listattavissa sarakkeissa voi olla rivinvaihtoja (LF).

Ainut, mikä tulee mieleen on ylimääräinen CR-merkki jossain välissä, ja tekstieditorisi tulkitsee sen rivinvaihdoksi..?
Otsikko: Vs: Tekstitiedostojen analysointi ja rakenteistaminen / siihen soveltuva skripti
Kirjoitti: JA5U - 10.05.16 - klo:22.07
Sitten tarvittaisiin esimerkki, jossa näin tapahtuu. En oikein näe, miten se olisi mahdollista, koska skripti tulostaa vain kaksi riviä, eikä riveille listattavissa sarakkeissa voi olla rivinvaihtoja (LF).

Ainut, mikä tulee mieleen on ylimääräinen CR-merkki jossain välissä, ja tekstieditorisi tulkitsee sen rivinvaihdoksi..?

Eletäänkö eri aikavyöhykkeillä? :) Vai vaan eri vrkrytmissä...

Testaamalla testasin nyt ja totesin, että ongelmat johtuvat rivistä, jolla ei ole tunnisteelle arvoa.
Eli jostain syystä kaikki ratkaisut sekoavat, jos rivillä on pelkkä tunniste eikä arvoa:
Koodia: [Valitse]
column_name;
Otsikko: Vs: Tekstitiedostojen analysointi ja rakenteistaminen / siihen soveltuva skripti
Kirjoitti: nm - 10.05.16 - klo:23.05
En onnistu toistamaan.  Edes puuttuva sarakkeen nimi ei haittaa:

input.txt:
Koodia: [Valitse]
column_1;value1
column_2;
column_3;value3
;value4
column_5;value5

Skriptin läpi ajettuna:

Koodia: [Valitse]
./tp.sh input.txt
Koodia: [Valitse]
column_1;column_2;column_3;;column_5
value1;;value3;value4;value5

Laita viestin liitteeksi tekstitiedosto, jossa vika esiintyy.
Otsikko: Vs: Tekstitiedostojen analysointi ja rakenteistaminen / siihen soveltuva skripti
Kirjoitti: JA5U - 11.05.16 - klo:11.33
Jopas on taas bittimaailman ihmeitä.
Eilen seditin kaikki ; loppuiset rivit muotoon ;- ja tokihan silloin toimi.

Ja valitettavasti tiedosto sisältää tietoa, jota ei voi luovuttaa eteenpäin.
Eikä oikein pätkäkään auta tässä tapauksessa.
Muutoin olisin heittänyt sellaisen heti aloituksessa.
Otsikko: Vs: Tekstitiedostojen analysointi ja rakenteistaminen / siihen soveltuva skripti
Kirjoitti: nm - 11.05.16 - klo:18.49
Jopas on taas bittimaailman ihmeitä.
Eilen seditin kaikki ; loppuiset rivit muotoon ;- ja tokihan silloin toimi.

En kyllä keksi, miten arvon puuttuminen voisi aiheuttaa ongelmia tuon skriptin kanssa. Siellä täytyy olla jotain muutakin erikoista rivinvaihtoihin liittyen.

Ja valitettavasti tiedosto sisältää tietoa, jota ei voi luovuttaa eteenpäin.
Eikä oikein pätkäkään auta tässä tapauksessa.
Muutoin olisin heittänyt sellaisen heti aloituksessa.

Yksi tapa löytää ongelmia aiheuttava kohta on leikata tiedostoa osiin puolittaen aina sen osan, jossa ongelma esiintyy. Lopulta pitäisi olla käsissä vain pieni pätkä, josta syyn voi löytää esimerkiksi heksaeditorin avulla. Silloin on myös mahdollista korvata arkaluontoiset merkkijonot geneerisillä nimillä esimerkkiä varten.
Otsikko: Vs: Tekstitiedostojen analysointi ja rakenteistaminen / siihen soveltuva skripti
Kirjoitti: JA5U - 11.05.16 - klo:20.59
Ei tää varmaan hirveästi auta, mutta CSV on siis seuraavanlainen:
Koodia: [Valitse]
rivi1_tunniste;rivi2_tunniste;rivi3_tunniste;...riviN_tunniste;
rivi1_arvo;rivi2_arvo;rivi3_arvo;rivi4_arvo
rivi4_arvo;rivi5_arvo...riviN_arvo;

Jaaaa, vaan nyt tuolla cat -v tarkasteltuna siellä onkin edelleen ^M merkkejä. Eli tuo ^M varmaan näyttäytyy tuollaisena "virheellisenä" CSVnä?

EDIT: yllättäen en enää muista, että kuinka sain osan niistä pois. SEDillä ei vaikuta luonnistuvan.
Otsikko: Vs: Tekstitiedostojen analysointi ja rakenteistaminen / siihen soveltuva skripti
Kirjoitti: nm - 11.05.16 - klo:23.00
Jaaaa, vaan nyt tuolla cat -v tarkasteltuna siellä onkin edelleen ^M merkkejä. Eli tuo ^M varmaan näyttäytyy tuollaisena "virheellisenä" CSVnä?

^M = \r = CR eli Carriage Return. DOS- ja Windows-ohjelmat käyttävät CR+LF:ää (\r\n) rivinvaihtona, kun Unixissa käytetään pelkkää LF:ää.

tr on paras työkalu yksittäisten tai peräkkäin toistuvien merkkien muuntamiseen ja poistoon:

Koodia: [Valitse]
tr -d '\r' < input.txt > output.txt
Jos syötteessä on CR-merkkejä, rivien määrä riippuu tulkinnasta. Jotkut ohjelmat tulkitsevat ne rivinvaihdoiksi (esim. gedit tekee niin) ja jotkut näyttävät ^M-merkinnän tai jotain muuta.
Otsikko: Vs: Tekstitiedostojen analysointi ja rakenteistaminen / siihen soveltuva skripti
Kirjoitti: JA5U - 11.05.16 - klo:23.49
Mitenkäs tämä tr komento yhdistetään find jatkeeksi?

Koodia: [Valitse]
find  . -name "*.txt" -type f -exec tr -d '\r' < jotain > jotain #mutta miten
Otsikko: Vs: Tekstitiedostojen analysointi ja rakenteistaminen / siihen soveltuva skripti
Kirjoitti: nm - 12.05.16 - klo:10.49
Mitenkäs tämä tr komento yhdistetään find jatkeeksi?

Koodia: [Valitse]
find  . -name "*.txt" -type f -exec tr -d '\r' < jotain > jotain #mutta miten

Esimerkiksi näin, jos haluat tehdä tiedostoille inplace-käsittelyn, eli kohdetiedosto on sama kuin lähde:

Koodia: [Valitse]
find  . -name "*.txt" -type f -exec sh -c 'cp {} "{}.tmp"; tr -d "\r" < "{}.tmp" > {}; rm "{}.tmp"' \;
Tai sedillä (mutta vain GNU-versioissa, ja muutenkin pienellä varauksella, koska eri sed-versiot saattavat käsitellä CR+LF-rivinvaihtoja eri tavoin):

Koodia: [Valitse]
find  . -name "*.txt" -type f -exec sed -i -e 's/\r//g' {} \;
Otsikko: Vs: Tekstitiedostojen analysointi ja rakenteistaminen / siihen soveltuva skripti
Kirjoitti: JA5U - 12.05.16 - klo:18.09
Mitenkäs tämä tr komento yhdistetään find jatkeeksi?

Koodia: [Valitse]
find  . -name "*.txt" -type f -exec tr -d '\r' < jotain > jotain #mutta miten

Esimerkiksi näin, jos haluat tehdä tiedostoille inplace-käsittelyn, eli kohdetiedosto on sama kuin lähde:

Koodia: [Valitse]
find  . -name "*.txt" -type f -exec sh -c 'cp {} "{}.tmp"; tr -d "\r" < "{}.tmp" > {}; rm "{}.tmp"' \;
Tai sedillä (mutta vain GNU-versioissa, ja muutenkin pienellä varauksella, koska eri sed-versiot saattavat käsitellä CR+LF-rivinvaihtoja eri tavoin):

Koodia: [Valitse]
find  . -name "*.txt" -type f -exec sed -i -e 's/\r//g' {} \;

Tämä oli muuten hyvä, mutta siinä kävi kuten epäilinkin eli nyt rivinvaihtoa tai välimerkkiä ei ole. Ilmeisesti tämä olisi ollut sitten sopivampi:
Koodia: [Valitse]
find  . -name "*.txt" -type f -exec sed -i -e 's/\r/\n/g' {} \;
Otsikko: Vs: Tekstitiedostojen analysointi ja rakenteistaminen / siihen soveltuva skripti
Kirjoitti: AimoE - 12.05.16 - klo:18.51
Tämä oli muuten hyvä, mutta siinä kävi kuten epäilinkin eli nyt rivinvaihtoa tai välimerkkiä ei ole. Ilmeisesti tämä olisi ollut sitten sopivampi:
Koodia: [Valitse]
find  . -name "*.txt" -type f -exec sed -i -e 's/\r/\n/g' {} \;

Olen yrittänyt käsitellä Nordean verkkopankista haettua tapahtumaluetteloa noin, mutta ei toiminut. Tarkoitan kohtaa "sed 's/\r/\n/g'".

Ensinnäkin, se sed-versio joka tulee Ubuntun mukana ei tunnusta \r-merkkiä, kuten nm oikein varoitti. Toiseksi, sedillä ei saa kiinni rivinvaihtoa, koska sed käsittelee inputtia rivi riviltä niin että rivinvaihto ei ole mukana. Jos rivinvaihdon haluaa korvata jollain, sedille pitää erikseen kertoa että input halutaan lukea yhtenä rivinä (http://stackoverflow.com/questions/1251999/how-can-i-replace-a-newline-n-using-sed), mikä on hirveän ruman näköistä.
 
Perlillä sen voi tehdä siististi:

Koodia: [Valitse]
perl -pe 's/\r\n//g' < input.txt > output.txt
mutta perl on liian järkäle näin pieneen juttuun.

Eipä yksittäisen tiedoston kanssa huomaa että cpua kuluu, mutta jos tiedostoja on paljon, niin sitten kannattaa nyplätä ja virkata sedin kanssa.

EDIT: Uups. Luin väärin kohdan  "sed 's/\r/\n/g'" koska olin juuri ollut käsittelemässä tätä Nordean tapahtumatiedoston tapausta. Tuo  "sed 's/\r/\n/g'" toimii jos sed tunnistaa \r:n. Mun tapauksessa siis oli tosiaan eri tilanne:  "sed 's/\r\n//g'".
Otsikko: Vs: Tekstitiedostojen analysointi ja rakenteistaminen / siihen soveltuva skripti
Kirjoitti: nm - 12.05.16 - klo:19.24
Tämä oli muuten hyvä, mutta siinä kävi kuten epäilinkin eli nyt rivinvaihtoa tai välimerkkiä ei ole.

Kokeilitko tr:llä? Testaa ensin yksittäistä tiedostoa, jossa ongelma esiintyy. Ilman näytettä en oikein keksi, mikä noissa muunnoksissa voisi aiheuttaa ongelmia.

Voit myös tutkia rivinvaihtoja heksaeditorilla. \r on ASCII-merkki 13 eli heksadesimaalina 0d. LF-rivinvaihto \n on 10 eli 0a
Otsikko: Vs: Tekstitiedostojen analysointi ja rakenteistaminen / siihen soveltuva skripti
Kirjoitti: JA5U - 12.05.16 - klo:21.29
Olis pitäny hieman tarkentaa tilannetta.
Tarkoitin siis sitä, että siinä ^M tilalla tulisi olla se rivinvaihto.
Eli nyt sen ^M tilalle ei tullut mitään ja kaksi riviä ovat yhdessä.
Ts. rivi1;asd^Mrivi2;asd -> rivi1;asdrivi2;asd

Toinen kysymys eli miten tuolle datamash komennolle voisi syöttää tuon findin tuloksen?
Nyt se herjaa
Koodia: [Valitse]
#find . -name '*.txt' -type f -exec datamash -t';' {} \;
datamash: invalid operation './asd.txt'
Lyhyesti päättelin, että se johtuisi tuosta ./asd.txt eli sen pitäisi olla asd.txt.
Tod.näk. olen kuitenkin väärässä :)
Otsikko: Vs: Tekstitiedostojen analysointi ja rakenteistaminen / siihen soveltuva skripti
Kirjoitti: nm - 12.05.16 - klo:21.51
Toinen kysymys eli miten tuolle datamash komennolle voisi syöttää tuon findin tuloksen?
Nyt se herjaa
Koodia: [Valitse]
#find . -name '*.txt' -type f -exec datamash -t';' {} \;
datamash: invalid operation './asd.txt'

Käyttöohjeen perusteella se lukee syötteen stdinistä ja käsitelty data annetaan ulos stdoutin kautta. Toimii siis kuten tr.

Koodia: [Valitse]
datamash -t';' transpose < input.txt > output.txt
Koodia: [Valitse]
find  . -name "*.txt" -type f -exec sh -c 'cp {} "{}.tmp"; datamash -t';' transpose < "{}.tmp" > {}; rm "{}.tmp"' \;
Otsikko: Vs: Tekstitiedostojen analysointi ja rakenteistaminen / siihen soveltuva skripti
Kirjoitti: JA5U - 13.05.16 - klo:21.44
No alkaahan tämä jo hiljalleen skulaamaan :)
Kaikkea oppii tai luulee oppivansa jatkuvasti - vielä, kun vaan muistaisi seuraavallakik kerralla, että miten se nyt olikaan.

Lopulta oikasin hieman:
Koodia: [Valitse]
find . -name '*.txt' -type f -exec bash -c 'txt2csv.sh "{}" > "{}".csv' \;
renamella muutin lopuksi txt.csv -> .csv, mutta joku hieno pikkujuttu varmaan mahdollistaisi suoraan csv päätteen.

Nyt pitäisi imasta nämä kantaan...
Toivottavasti kukaan ei tässä vaiheessa totea, että miksi nähdä näin paljon vaivaa, kun asian olisi voinut hoitaa jotenkin toisin  ;D
...mutta aikuisten oikeasti, jos on joku virtaviivaisempi keino, niin saa toki kertoa.
Otsikko: Vs: Tekstitiedostojen analysointi ja rakenteistaminen / siihen soveltuva skripti
Kirjoitti: JA5U - 11.10.16 - klo:17.17
No eipä tämä nyt suju.

Nuo ^M merkit kummitelevat edelleen ja tekevät mielenkiintoisia omituisuuksia PHP:ssä fgetcsvllä.

Ne pitäisi siis saada pois, mutta miten?

Ei auta:
Koodia: [Valitse]
find . -type f -name "*.txt" -exec vi {} -c ':silent!' -c ':%s/\^M/\r/G' -c ':wq' \;
Ei auta:
Koodia: [Valitse]
find . -type f -name "*.txt" -exec vi {} -c ':silent!' -c ':%s/<Ctrl-V><Ctrl-M>/\r/g' -c ':wq' \;

EDIT:
Merkillinen havainto, kun komennolla
Koodia: [Valitse]
cat tarkastelee tiedostoa, niin ^M sisältävän rivin alkuosa ei tulostu.
Kuitenkin
Koodia: [Valitse]
cat -v komennolla koko rivi tulostuu.
Rivi on siis muotoa: teksti^Mlisaatekstia (cat -v) tai lisaatekstia (cat)
Otsikko: Vs: Tekstitiedostojen analysointi ja rakenteistaminen / siihen soveltuva skripti
Kirjoitti: nm - 11.10.16 - klo:17.29
Olisi helpompaa neuvoa, jos pystyisit antamaan pätkän ongelmatiedostosta esimerkkinä. Muuten menee täysin arvailuksi, miten nuo rivinvaihdot ovat seonneet.
Otsikko: Vs: Tekstitiedostojen analysointi ja rakenteistaminen / siihen soveltuva skripti
Kirjoitti: jekku - 11.10.16 - klo:17.55
No eipä tämä nyt suju.

Nuo ^M merkit kummitelevat edelleen ja tekevät mielenkiintoisia omituisuuksia PHP:ssä fgetcsvllä.

Ne pitäisi siis saada pois, mutta miten?
.........


Oletkos moista kokeillut?
Koodia: [Valitse]
:~# aptitude search dos2unix
p   dos2unix       
Otsikko: Vs: Tekstitiedostojen analysointi ja rakenteistaminen / siihen soveltuva skripti
Kirjoitti: JA5U - 11.10.16 - klo:18.10
Kyllä, dos2unix on ollut kokeilussa, mutta sama lopputulos.  :-\

Eikös tuossa ylhäällä ole esimerkkirivi:
Rivi on siis muotoa: teksti^Mlisaatekstia (cat -v) tai lisaatekstia (cat)

cat -v
Koodia: [Valitse]
riviX;zxczxc
ongelmarivinalku;asd^Mjaloppu;wasd
riviY;xczxcz

cat
Koodia: [Valitse]
riviX;zxczxc
jaloppu;wasd
riviY;xczxcz
Otsikko: Vs: Tekstitiedostojen analysointi ja rakenteistaminen / siihen soveltuva skripti
Kirjoitti: nm - 11.10.16 - klo:18.14
Eikös tuossa ylhäällä ole esimerkkirivi:
Rivi on siis muotoa: teksti^Mlisaatekstia (cat -v) tai lisaatekstia (cat)

Haluaisin nähdä palan alkuperäisestä tiedostosta ilman mahdollista editorin tai päätteen tekemää muunnosta, jotta voisin tutkia sitä binäärimuodossa heksaeditorilla. Muuten on vaikea arvata, mitä tiedosto oikeasti sisältää.

hexdumpin listaus kelpaa myös:

Koodia: [Valitse]
hexdump -C tiedosto.txt
Otsikko: Vs: Tekstitiedostojen analysointi ja rakenteistaminen / siihen soveltuva skripti
Kirjoitti: JA5U - 11.10.16 - klo:18.59
Muokkasin itselleni tällaisen, joka ratkaisi asian, mutta aiheutti tyypillisen "nokka irtoaa, niin pyrstö tarttuu" eli menetin ääkköset:

Koodia: [Valitse]
#make a backup
cp $1 $1.orig

#Tekee jonku muutoksen ä->a tmv.
iconv -t ascii//TRANSLIT $1.orig > $1.temp

#Strip out other unprintable characters  -whatevs
strings $1.temp > $1

#Remove temp file.
rm $1.temp

Ja jos käytän tiedoston Sublimen kautta, niin ongelmat ts.merkit katoavat eikä dataa menetetä.
Joten teen siis komennon joka pyöräyttää tiedostot taustalla Sublimen kautta.

Tässä kuitenkin vielä UUSI hexdump ongelmakohdasta:
Koodia: [Valitse]
00000000  65 72 65 68 64 79 73 3b  0a 65 74 75 6e 69 6d 69  |erehdys;.etunimi|
00000010  3b 74 65 72 6f 0a 73 75  6b 75 6e 69 6d 69 3b 61  |;tero.sukunimi;a|
00000020  6e 74 65 72 6f 0a 6c 61  68 69 6f 73 6f 69 74 65  |ntero.lahiosoite|
00000030  3b 6b 6f 74 69 6b 61 74  75 20 38                 |;kotikatu 8|
0000003b

Otsikko: Vs: Tekstitiedostojen analysointi ja rakenteistaminen / siihen soveltuva skripti
Kirjoitti: nm - 11.10.16 - klo:20.42
Jees, ongelma näkyi siinä dumpissa jonka ehdit poistaa, eli tiedostossa oli enimmäkseen LF-rivinvaihdoilla erotettuja rivejä, mutta yksi CR (0x0d) kohdassa, jossa kuuluisi olla rivinvaihto. Jokin on siis pudottanut siitä kohdasta LF:n (0x0a) pois tai korvannut sen CR:llä.

Varmin ratkaisu olisi käyttää ensin dos2unix-komentoa (tai vastaavaa sed-skriptiä) siltä varalta, että vastaan tulee CR+LF-rivinvaihtoja, mutta jatkaa sitten muuntamalla yksinäiset CR-rivinvaihdot LF-rivinvaihdoiksi. Eli jotakuinkin tähän tapaan:

Koodia: [Valitse]
dos2unix -n tiedosto.txt temp.txt
Koodia: [Valitse]
tr '\r' '\n' < temp.txt > korjattutiedosto.txt

Tämä toimii siis olettaen, että CR-merkkejä on vain sellaisissa kohdissa, joissa kuuluu olla rivinvaihto. Jos niitä on myös muualla, olet syvässä suossa.
Otsikko: Vs: Tekstitiedostojen analysointi ja rakenteistaminen / siihen soveltuva skripti
Kirjoitti: JA5U - 11.10.16 - klo:22.20
Tämä toimii siis olettaen, että CR-merkkejä on vain sellaisissa kohdissa, joissa kuuluu olla rivinvaihto. Jos niitä on myös muualla, olet syvässä suossa.

Eli kuten tuossa esimerkkirivillä on keskellä riviä ^M, niin olen suossa?

Mutta jos saan tuon sublimen toimimaan, niin en kenties olekaan...

EDIT:
No eihän se Sublimessä pyöräyttäminen muuttanut mitään, kun se tehtiin komentorivin kautta.
Jos avaa käyttöliittymässä, niin silloin kyllä tiedostot korjaantuvat pelkällä 'save' toiminnolla.

HUOH...
Otsikko: Vs: Tekstitiedostojen analysointi ja rakenteistaminen / siihen soveltuva skripti
Kirjoitti: nm - 11.10.16 - klo:22.56
Tämä toimii siis olettaen, että CR-merkkejä on vain sellaisissa kohdissa, joissa kuuluu olla rivinvaihto. Jos niitä on myös muualla, olet syvässä suossa.

Eli kuten tuossa esimerkkirivillä on keskellä riviä ^M, niin olen suossa?

Kolme mahdollista tapausta:

1.  CR-merkkejä on vain keskellä riviä, mahdollisesti satunnaisissa paikoissa. Oikeat rivinvaihdot on merkitty LF:llä tai CR+LF:llä.

Ratkaisu: poistetetaan kaikki CR-merkit. Tähän on esitetty sekä tr- että sed-komennot jo aiemmin.


2. CR-merkkejä on vain sellaisissa paikoissa, joissa kuuluu olla rivinvaihto, mutta LF saattaa puuttua.

Ratkaisu: dos2unix ja yksittäisten CR-merkkien muuntaminen LF-merkeiksi esim. tr-työkalulla, kuten esitin edellisessä viestissäni.


3. Yksittäisiä CR-merkkejä on sekä rivinvaihtojen kohdilla että keskellä riviä.

Mikään triviaali poisto tai muunnos ei pysty päättelemään, merkkaako CR rivinvaihtoa vai onko se turha. Tässä on todellinen ongelma, joka ei ehkä ole ratkaistavissa ilman heuristiikkaa tai koneoppimista. Jos tilanne on tämä, olisi todennäköisesti helpompaa lähteä aivan alusta selvittämään, mistä CR-merkit ovat dataan päätyneet.


Aiempi hexdump-listaus, jonka poistit (ja korvasit siistityllä esimerkillä jossa ei ole ainoatakaan CR-merkkiä), viittasi tapaukseen 2 tai 3. Siinä ei siis ollut CR:ää rivin keskellä vaan rivinvaihdon kohdalla:
Koodia: [Valitse]
etunimi;tero^Msukunimi;anteroUudessa esimerkissä tuo CR on vaihtunut LF:ksi:
Koodia: [Valitse]
etunimi;tero
sukunimi;antero
Jos siis datassa esiintyy sekä tällaisia tapauksia että yksittäisiä CR-merkkejä keskellä riviä vaikkapa nimen sisällä, olet pulassa.
Otsikko: Vs: Tekstitiedostojen analysointi ja rakenteistaminen / siihen soveltuva skripti
Kirjoitti: JA5U - 11.10.16 - klo:23.05
Latasin wxhexeditorin ja siinä virhekohdassa näkyy nuotti.

Taisin ajaa findillä kansioon nuo korjaukset, jonka jälkeen otin uuden hexdumpin, kun huomasin, että aiemmasta puuttui c kahva.
Koodia: [Valitse]
00000000  79 72 69 74 79 73 3b 0a  65 74 75 6e 69 6d 69 3b  |yritys;.etunimi;|
00000010  48 65 72 72 61 0d 73 75  6b 75 6e 69 6d 69 3b 4d  |Herra.sukunimi;M|
00000020  61 6a 75 72 69 0a 6c 61  68 69 6f 73 6f 69 74 65  |ajuri.lahiosoite|
00000030  3b 4b 6f 74 69 6b 61 74  75 20 34 0a              |;Kotikatu 4.|
0000003c

Jos tarkastelen tiedostoa komennolla
Koodia: [Valitse]
od -ctx1 test.txt
niin siinä näkee taas sen, että tuo yksi on \r ja loput \n.
Otsikko: Vs: Tekstitiedostojen analysointi ja rakenteistaminen / siihen soveltuva skripti
Kirjoitti: nm - 11.10.16 - klo:23.17
Jos tarkastelen tiedostoa komennolla
Koodia: [Valitse]
od -ctx1 test.txt
niin siinä näkee taas sen, että tuo yksi on \r ja loput \n.

Jep, juuri niin. Ja tässä tapauksessa merkin \r (= CR = ^M = 0d) kohdalla kuuluisi olla rivinvaihto, vai mitä? Eli se pitäisi muuntaa \n:ksi (= LF = 0a).

Esiintyykö jossain muualla datassa \r kentän sisällä eli vaikkapa keskellä etunimeä? Jos ei, riittää esitetty tr-muunnos:

Koodia: [Valitse]
tr '\r' '\n' < tiedosto.txt > korjattutiedosto.txt
dos2unixilla voisi kuitenkin siistiä mahdolliset CR+LF:t ensin pois, kuten aiemmin esitin. Muuten niiden tilalle tulee kaksinkertainen rivinvaihto.
Otsikko: Vs: Tekstitiedostojen analysointi ja rakenteistaminen / siihen soveltuva skripti
Kirjoitti: JA5U - 12.10.16 - klo:00.51
No nyt  :)

Tein nm.sh "skriptin", kun en muutoin osannut tätä ajaa oikeilla parametreillä:
Koodia: [Valitse]
tr '\r' '\n' < $1 > fixit/$1

Kiitokset!

EDIT:
Siis lopullinen ratkaisu:
Koodia: [Valitse]
find . -type f -name "*.txt" -exec ./nm.sh {} \;