Sida 1 av 1
Sök i en fil, ersätt i en annan [LÖST]
Postat: 16 jan 2009, 19:13
av djkmmo
Jag har letat i historien av kategorin, men inte hittat något svar, så jag frågar istället.
Ingress:
Jag skulle behöva söka upp rader i en fil (låt oss kalla den foo.old) efter förekomster utav rader i en annan fil (låt oss, helt otippat, kalla den för foo.new) där början av raden är samma som som i foo.old. Om sådana förekomster hittas skall raden i foo.new ersättas med innehållet i foo.old.
Förklaring:
Jag behöver översätta ett program till svenska, där översättningen görs via en php-fil. Det är en kille som redan har översatt programet, men tyvärr verkar han ha översatt fel fil. Den fil han översatt innehåller (foo.old) en delmängd av de variabler som skall översättas, men inte alla. Jag vill alltså söka upp de strängar han har översatt i foo.old, se om variabeln finns i foo.new och i så fall ersätta hela raden. foo.new är den "riktiga" översättningsfilen och är på engelska, så om det är en variabel han inte översatt så skall den raden baraa hoppas över, så går de att översätta efteråt. Det som skall sökas är alltså php-variabler (alla börjar med $), om det hjälper. Dock kan det finnas mellanslag och tabbar innan variabeln kommer, men de står alltid först på raden.
Detta borde vara enkelt att göra med grep, awk eller sed, men eftersom att jag inte är någon programerare så vet jag inte hur jag skall få ihop det. Det enda jag funnit är ersättning av enskilda ord eller regexp av mönster, men här koan ju mönstren se ut lite hur som helst och skall läsas från en fil. Är det någon som kan hjälpa mig?
Re: Sök i en fil, ersätt i en annan
Postat: 16 jan 2009, 19:29
av Urban Anjar
Har ingen färdig lösning, men diff foo.old foo.new ger i alla fall koll på vilka skillnader det är mellan filerna
Re: Sök i en fil, ersätt i en annan
Postat: 16 jan 2009, 19:40
av djkmmo
Urban Anjar skrev:Har ingen färdig lösning, men diff foo.old foo.new ger i alla fall koll på vilka skillnader det är mellan filerna
Men diff ger väl svar baserat på radnummer? OM RAD1 != RAD2 SÅ visa?
Det kan ju vara väl värt att nämna kanske: radnumret för förekomsterna kan vara
helt olika, så $variabel1 kan finnas på rad 563 i foo.old och på rad 1268 i foo.new och $variabel2 kan finnas på rad 1576 i foo.old och på rad 16 i foo.new. Man måste med andra ord (tror jag) söka
hela foo.old, rad för rad och jämföra den med hela foo.new, rad för rad.
Re: Sök i en fil, ersätt i en annan
Postat: 16 jan 2009, 20:15
av Konservburk
Plocka fram de rader du vill ersätta med från filen foo.new... loopa över dem och ersätt i filen foo.old.
Re: Sök i en fil, ersätt i en annan
Postat: 16 jan 2009, 20:23
av djkmmo
Konservburk skrev:Plocka fram de rader du vill ersätta med från filen foo.new... loopa över dem och ersätt i filen foo.old.
Jo det är ju det jag vill göra, men hur gör jag? Kom i håg att jag inte är ngn programmerare; jag bara vet att det måste vara lätt att göra, men jag vet inte hur man lätt gör det

.
Pretty, pretty please Konservburk, förbarma dig över mig...
Re: Sök i en fil, ersätt i en annan
Postat: 16 jan 2009, 20:27
av Konservburk
Ge exempel på hur de intressanta raderna kan se ut ...
annars blir det lite svårt för mig att komma med något konkret kod-exempel

Re: Sök i en fil, ersätt i en annan
Postat: 16 jan 2009, 20:50
av djkmmo
Konservburk skrev:Ge exempel på hur de intressanta raderna kan se ut ...
annars blir det lite svårt för mig att komma med något konkret kod-exempel

Aha, visst kan jag göra det. Jag kan t.o.m. göra mer än så, jag kan bifoga filerna

. Men här kommer lite exempel också:
foo.new:
Kod: Markera allt
$lang_comphire_heading = "Company Hierarchy: Company Information";
$lang_comphire_relationalhierarchy = "Relational Hierarchy";
$lang_comphire_employee = "Employee";
$lang_comphire_definitionlevel = "Definition Level";
$lang_comphire_telephone = "Telephone";
$lang_comphire_fax = "Fax";
$lang_comphire_email = "Email";
$lang_comphire_url = "URL";
$lang_comphire_logo = "Logo";
$lang_comphire_selecthie = "Select Hierarchy";
$lang_comphire_selectdef = "Select Def. Level";
$lang_compstruct_heading = "Company Info : Company Structure";
$lang_compstruct_Dept_Id = "Department ID:";
$lang_compstruct_frmSub_divisionHeadingAdd = "Add a sub-division to";
$lang_compstruct_frmSub_divisionHeadingEdit = "Edit";
$lang_compstruct_Name = "Name";
$lang_compstruct_Type = "Type";
$lang_compstruct_Division = "Division";
$lang_compstruct_Description = "Description";
$lang_compstruct_Department = "Department";
foo.old
Kod: Markera allt
$lang_Error_PleaseCorrectTheFollowing = "Rätta till följande";
$lang_Error_SelectAtLeastOneRecordToDelete = "Välj minst en uppgift att ta bort";
$lang_Error_DoYouWantToDelete = "Vill du ta bort?";
$lang_Error_EnterDate = "Ange datum?";
$lang_Error_PleaseSelectAYear = "Välj ett år";
$lang_Error_PleaseSelectAnEmployee = "Välj en anställd";
$lang_Error_DoYouWantToContinue = "Vill du fortsätta?";
$lang_Error_PleaseSelectAnEmployee = "Välj en anställd";
$lang_Error_ShouldBeNumeric = "Måste vara numeriskt";
$lang_Error_FollowingErrorsWereFound = "Följande fel hittades";
$lang_Error_AreYouSureYouWantToDelete = "Är du säker på att du vill ta bort";
$lang_Error_AccessDenied = "Åtkomst nekad";
//leave
$lang_Error_PleaseSelectAValidFromDate = "Välj ett giltigt Från-datum";
$lang_Error_PleaseSelectAValidToDate = "Välj ett giltigt Till-datum";
$lang_Error_PleaseSelectALeaveType = "Välj en frånvaroorsak";
$lang_Error_LeaveDateCannotBeABlankValue = "Frånvarodatum kan inte vara ett tomt värde!";
$lang_Error_NameOfHolidayCannotBeBlank = "Namn på semester kan inte vara tomt";
$lang_Error_NoLeaveTypes = "Inga ledighetstyper";
$lang_Error_NoRecordsFound = "Inga uppgifter hittades!";
$lang_Error_InvalidDate = "Ogiltigt datum";
I den bifogade zip-filen skall innehållet i lang_sv_full.php ersätta raden i lang_default_sv_full.php omm variabelnamnet är samma.
Re: Sök i en fil, ersätt i en annan
Postat: 16 jan 2009, 21:47
av Konservburk
Kod: Markera allt
sed -n '/^\s*$\S\+\s*=\s*/p' lang_sv_full.php |
(
IFS="=$IFS"
while read a b
do sed -i "s|^\(\s*$a\s*=\s*\).*|\1$b|" lang_default_sv_full.php
done
)
Förklaring:
sed -n '/^\s*$\S\+\s*=\s*/p' lang_sv_full.php
Plocka ut rader från lang_sv_full.php som
börjar ^ med
noll eller flera mellanrum \s*
följt av ett dollartecken $
följt av ett eller flera tecken som inte är mellanrum \S\+
följt av noll eller flera mellanrum \s*
följt av ett likhetsteken =
följt av noll eller flera mellanrum \s*
IFS="=$IFS"
Gör så att likhetsteken räknas som mellanrum
while read a b
do ...
done
Loopa över de utplockade raderna och ta i varje varv fram
det som står innan likhetstecknet som $a
och det som står efter likhetstecknet som $b
sed -i "s|^\(\s*$a\s*=\s*\).*|\1$b|" lang_default_sv_full.php
Leta reda på rader från lang_default_sv_full.php som
börjar ^ med
noll eller flera mellanrum \s*
följt av det som stod innan likhetstecknet i den andra filen $a
följt av noll eller flera mellanrum \s*
följt av ett likhetsteken =
följt av noll eller flera mellanrum \s*
och ersätt allt som kommer därefter .* med
det som stod efter likhetstecknet i den andra filen $b
Re: Sök i en fil, ersätt i en annan
Postat: 16 jan 2009, 21:55
av David Andersson
En slags databasoperation. Det finns trevliga unix-kommandon som
join och sånt. Ett nätt
perl-script som läser
old till en hash, uppdaterar hashen med
new och sedan skriver ut hashen till
newnew kunde ha klarat biffen. Men det finns ett par saker som gör det här lite krångligare.
1) Datat är
logisk grupperat. Det är inte säkert att grupperingen är likadan i old och new. Grupperingen är antagligen önskvärd ur underhållssynpunkt. Den kan inte automatåterskapas. Hur bevara ordning i old och new i newnew om de har delvis olika innehåll? Hur bevara tomrader på rätt ställen? Glöm inte kommentarer och att data har "fritt format" (space, tab och i princip newline lite varsomhelst).
2) Datat är
inkonsistent. Samma variabel sätts ibland på flera ställen. Ibland till samma värden vilket inte är logiskt fel, men ibland till olika värden. En simpel process kan strunta i det och bara ta första eller sista. Men en
människa borde granska dubbleringarna och ta bort eller definiera om den som är minst rätt.
Kommandorad för att upptäcka dubbleringar i en fil:
Kod: Markera allt
for i in lang_sv_full.php lang_default_sv_benefits.php lang_default_sv_full.php; do echo === $i ===; egrep -h -o '\$[a-zA-Z0-9_]+' lang_sv_full.php | sort | uniq -d; done | less
Lista värdena av dubblerade definitioner:
Kod: Markera allt
for i in lang_sv_full.php lang_default_sv_benefits.php lang_default_sv_full.php; do echo === $i ===; egrep -ho '\$[a-zA-Z0-9_]+' $i | sort | uniq -d | tr -d '$' | xargs -i grep -w {} $i; done | less
Variabler som följs av olika [0] och [1] listas av ovanstående kommando men är inte dubbleringar så de är okej. Gå ur
less med q.
Fixa 2) så funderar vi andra på en kommandorad som klarar 1).
EDIT: bug i första kommandoraden: andra förekomsten av lang_sv_full.php ska ändras till $i
Re: Sök i en fil, ersätt i en annan
Postat: 16 jan 2009, 22:07
av David Andersson
djkmmo skrev: så om det är en variabel han inte översatt så skall den raden baraa hoppas över, så går de att översätta efteråt.
Det är lätt hänt för en männska att missa enstaka engelska rader bland många svenska. Processen (som inte finns än) kan i princip upptäcka och på nåt sätt markera de definitioner den inte ändrat, så att de inte missas efteråt. Det är en lite komplicerande faktor, men kan vara värt det.
Re: Sök i en fil, ersätt i en annan
Postat: 17 jan 2009, 00:25
av djkmmo
Konservburk skrev:Kod: Markera allt
sed -n '/^\s*$\S\+\s*=\s*/p' lang_sv_full.php |
(
IFS="=$IFS"
while read a b
do sed -i "s|^\(\s*$a\s*=\s*\).*|\1$b|" lang_default_sv_full.php
done
)
Förklaring:
sed -n '/^\s*$\S\+\s*=\s*/p' lang_sv_full.php
Plocka ut rader från lang_sv_full.php som
börjar ^ med
noll eller flera mellanrum \s*
följt av ett dollartecken $
följt av ett eller flera tecken som inte är mellanrum \S\+
följt av noll eller flera mellanrum \s*
följt av ett likhetsteken =
följt av noll eller flera mellanrum \s*
IFS="=$IFS"
Gör så att likhetsteken räknas som mellanrum
while read a b
do ...
done
Loopa över de utplockade raderna och ta i varje varv fram
det som står innan likhetstecknet som $a
och det som står efter likhetstecknet som $b
sed -i "s|^\(\s*$a\s*=\s*\).*|\1$b|" lang_default_sv_full.php
Leta reda på rader från lang_default_sv_full.php som
börjar ^ med
noll eller flera mellanrum \s*
följt av det som stod innan likhetstecknet i den andra filen $a
följt av noll eller flera mellanrum \s*
följt av ett likhetsteken =
följt av noll eller flera mellanrum \s*
och ersätt allt som kommer därefter .* med
det som stod efter likhetstecknet i den andra filen $b
Djupa, djupa tackar och många bockar! Fantasktiskt pedagogisk förklaring också. Det här kommer jag att kunna återanvända många ggr. Det är inte helt sällan som folk börjar att översätta något och slutar alt. har översatt en gammal version av programmet, där mycket av den gammla översättningen går att återanvända, men är spridd över filen. Likadant är det ibland en del som tar bort vagnreturer och kommntarer i översättningen, antagligen för att trimma filerna, vilket gör det ännu mer omöjligt att göra arbetet manuellt. Jag får nästa tårar i ögonen nu...
Så nu sparar jag det bara och byter ut lang_sv_full.php mot $1 och lang_default_sv_full.php mot $2 för att istället kunna specificera filerna på kommandoraden? Verkligen vackert.
David skrev:1) Datat är logisk grupperat.
Helt riktigt, även om en del förstör den logiska uppdelningen; se ovan. Med detta går den att återställa igen, till allas fördel.
David skrev:2) Datat är inkonsistent.
Hmmm... Det där är ju inte heller alls dumt. och om man i den första sätter bara en av lang_sv_full.php eller lang_default_sv_benefits.php och använder samma i egrep-delen så får man fram ev. dubletter i filen. För ibland kan det t.o.m. vara så fel. Saker som tillhört en modul flyttas till en annan och så råkar det följa med för mycket när någon klipper och klistrar, så att den variabel deklareras två ggr. i en fil... Eftersom att det handlar om översättningar så är det inte säkert att det syns. Programet kommer ju inte att dö av segmenteringsfel för det. Men det är ju inte så snyggt.
Re: Sök i en fil, ersätt i en annan
Postat: 17 jan 2009, 01:05
av djkmmo
Nu har jag provat och det fungerade aldeles perfekt, precis som det skulle

.