Resurs  

Introduktion till kommandot tr

Behandlar: Introduktion till kommandot tr.


 

Hur man byter tecken mot tecken, parvist

Det finns många situationer vid textbearbetning då man skulle vilja byta alla stora bokstäver i en text mot små. Detta är ett exempel på att parvist byta tecken mot varandra: 'A' mot 'a', 'B' mot 'b', osv. För att åstadkomma detta kan man ha stor nytta av kommandot tr. Följande anrop skulle t.ex. åstadkomma det önskade:
    tr '[A-Z]ÅÄÖ' '[a-z]åäö'  < indatafil

Observera att det inte är reg.uttryck, som är argument här (även om de liknar dem till viss del). Det är i stället s.k. teckenföljder, alltså uppräkningar av tecken. Ordningen som man skriver tecknen i  är väldigt viktig i en teckenföljd, eftersom man ju byter tecknen parvist (1:a tecknet mot 1:a, 2:a mot 2:a, osv.). Jämför detta med ett reg.uttryck, där teckenmängder bara anger ett antal möjliga/alternativa tecken, av vilka exakt ett tecken matchar. För teckenmängder i reg.uttryck är därför ordningen inte viktig:  [abcde]  betecknar precis samma mängd som [edcba] gör.

För teckenföljder däremot, så måste man ge tecknen till  tr  i den ordning man vill få dem bytta. Anropet nedan:

          tr 'abcde' 'vwxyz'  < indatafil

byter alla 'a' mot 'v', alla 'b' mot 'w', osv. Det ger en helt annan effekt än följande anrop:

          tr 'edcba' 'vwxyz'  < indatafil

som byter alla 'e' mot 'v', alla 'd' mot 'w', osv.

 

Hur man ger teckenföljderna till tr

Man behöver inte räkna upp alla tecken utan kan sätta bindestreck för att markera ett intervall. T.ex kan vi lika gärna skriva

    tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZÅÄÖ' 'abcdefghijklmnopqrstuvwxyzåäö'  < indatafil
som vi skriver

    tr '[A-Z]ÅÄÖ' '[a-z]åäö'  < indatafil

fast vi väljer förstås det kortare.

Dock måste tecknen i intervallet komma efter varandra i ASCII-koden, och det gör inte åäö, så därför kan man inte skriva [a-ö]. Faktiskt så kommer inte ens åäö direkt efter varandra, och inte ens i rätt ordning. Men det är för att ASCII-koden är utarbetad i USA och våra svenska tecken har fått stoppas in i efterhand på andra teckens ställen (läs mer kodningshistoriken vid intresse).

Mängden svenska små tecken skrivs därför [a-z]åäö. Tänk dock på att när ni skriver intervall med bindestreck, så måste hakparenteser sättas runt intervallet: alltså [a-z]. Undvik att skriva hakar kring hela mängden, utan skriv hakarna bara runt själva intervallen. Skydda sedan som vanligt uttrycket från kommandoskalet genom att omgärda det med enkla citationstecken.

En viktig sak som man inte får glömma då man anropar tr är att det måste vara exakt lika många tecken i båda mängderna: "byt in"- och "byt ut"-mängderna ska vara lika stora. tr ger inga felmeddelanden vid skillnader utan arbetar igenom texten med resultat därefter. Samma sak gäller om man glömmer hakparanterser runt ett intervall (exempelvis är 'a-j' inte 10 tecken utan bara 3, rätt ska vara '[a-j]'). Så kom ihåg hakar och lika många tecken på båda "sidor".  

Hur man specificerar indata till tr

Som du kanske märkte ovan, så kom inte indatafilen som vanligt direkt som sista argument. Det beror på att tr tyvärr är rätt larvig och inte tillåter någon fil som argument! I stället kräver den att få sin indata (för någon text måste den ju ha att jobba på) via STDIN (standard input). Detta innebär att du kan anropa antingen helt utan fil:

    tr '[A-Z]ÅÄÖ' '[a-z]åäö'

men då får du skriva in den text du vill bearbeta direkt på skärmen. Du kan skriva text över flera rader, om du vill. Först när du trycker CTRL-D så avlutar du inmatningen från skärmen och då reagerar tr med att skriva ut texten igen fast alla stora bokstäver är nu små.

Det andra alternativet är att dirigera om STDIN så att input tas från en fil istället för från skärmen. Det är vad vi gjorde förut och det var därför det fanns en < på kommandoraden. Märk väl att detta tecken är ett som tolkas av kommandoskalet. tr "ser" inget av det som står efter < indatafil. Det är shell, som ser till att ställa om STDIN till indatafil, så att tr (som tror att den läser från STDIN) i verkligheten läser från indatafil.

    tr '[A-Z]ÅÄÖ' '[a-z]åäö'  < indatafil
 

Andra sätt att specificera teckenföljderna

Ibland behöver man byta många olika tecken mot exakt samma tecken. Det blir ganska jobbigt att skriva:

    tr '[A-Z]ÅÄÖ' 'wwwwwwwwwwwwwwwwwwwwwwwwwwww'  < indatafil

så därför finns det en kortnotation för att få ett tecken upprepat. Använd en stjärna * efter tecknet som ska upprepas, och omge det hela med hakparenteser:

    tr '[A-Z]ÅÄÖ' '[w*]'  < indatafil

så fyller tr själv på med så många w som behövs.

Det går givetvis att byta in vilket tecken som helst, t.ex. kan man stoppa in radbrytningstecken eller ett tabulatortecken (en tab) om man så skulle vilja. Här nedan byter vi varje blank mot en tab:

    tr ' ' '\t'  < indatafil
 

Flaggor som man kan ge till tr

De två viktigaste flaggorna är Det finns också en tredje flagga, men ska man ge den får man inte ge mer än en teckenföljd.