Herjaa pukkaa:
# 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ä:
sed --help
-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 2Sed 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 3Skripti ei ratkaise esitettyä tehtävää. Olkoon toistuva merkkijono esimerkiksi "yks kaks;28.04.2016 10:11:22":
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:
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:
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.