Jag har temp
-fil med lite gemener och gemener.
Ingång
Innehåll i min temp
-fil:
hi Jigar GANDHI jiga
Jag vill konvertera alla övre till nedre .
Kommando
Jag försökte följande kommando:
sed -e "s/[A-Z]/[a-z]/g" temp
men fick fel utdata.
Output
Jag vill ha det som:
hi jigar gandhi jiga
Vad som måste vara i ersättare delen av argument för sed
?
Kommentarer
- Se även Hur konverterar man UTF-8 txt-filer till alla versaler i bash?
Svar
Om din inmatning bara innehåller ASCII-tecken kan du använda tr
som:
eller (mindre lätt att komma ihåg och skriva IMO; men inte begränsat till ASCII-latinska bokstäver, men i vissa implementeringar inklusive GNU tr
, fortfarande begränsad till enbyte-tecken, så i UTF-8-lokaler, fortfarande begränsad till ASCII-bokstäver): / p>
tr "[:upper:]" "[:lower:]" < input
om du måste använda sed
:
sed "s/.*/\L&/g" < input
(här antar vi GNU-implementeringen).
Med POSIX sed
behöver du ange alla translitterationer och sedan kan du välja vilken bokstäver du vill konvertera:
sed "y/AǼBCΓDEFGH.../aǽbcγdefgh.../" < input
Med awk
:
awk "{print tolower($0)}" < input
Kommentarer
- Observera att
\L
är ett GNU-tillägg. -
\L
fungerar hittills bra för mig. Tänd punkten som du försöker göra GNU-tillägg - @JigarGandhi.
sed
är ett Unix-kommando. Olika system har olika varianter med olika beteende och d-funktionalitet. Tack och lov finns det numera ’ en standard som passar bäst så att du kan räkna med en minsta uppsättning funktioner som är gemensamma för alla.\L
är inte bland dem och introducerades av GNUsed
(matchar samma operatör i standardex
/vi
) och är vanligtvis inte tillgängligt i andra implementeringar. - Observera att vissa
tr
-implementeringar som GNUtr
don ’ t fungerar ordentligt i flera byte-platser (de flesta är nuförtiden, provaecho STÉPHANE | tr '[:upper:]' '[:lower:]'
till exempel). På GNU-system föredrar du kanskesed
-varianten ellerawk
’ stolower()
. - Lätt korrigering:
sed 's/.*/\L&/g' < input
.\1
referensen till matchad substring vann ’ t såvida du inte anger substringen med parentes som wurtle gör i hans. Det är dock ’ lite renare att använda&
för att representera hela matchningen, som visas
Svar
Med vim är det super enkelt:
$ vim filename gg0guGZZ
Öppnar filen gg
går till första raden, 0
, första kolumnen. Med guG
, sänker bokstäverna för alla tecken tills botten av filen. ZZ
sparar och avslutas.
Den ska hantera nästan vad som helst du kastar åt den; den ”kommer att ignorera siffror, det” kommer att hantera icke ASCII.
Om du vill göra det motsatta, vänd de små bokstäverna till versaler, byt u
ute efter en U
: gg0gUGZZ
och du är inställd.
Kommentarer
- Lol ” superenkelt ”
- detta gör självklart inte ’ t skalar bra för många filer
- @CoreyGoldberg
vim file1 file2 fileetc
och då skulle något som:bufdo gg0guG:w<CR>
troligen / i> arbeta för valfritt antal filer. Har dock inte testat det! - @TankorSmash som fortfarande inte ’ t skalas till ett stort antal filer
Svar
Jag gillar dd
för detta själv.
<<\IN LC_ALL=C 2<>/dev/null \ dd conv=lcase hi Jigar GANDHI jiga IN
… får …
hi jigar ghandi jiga
LC_ALL=C
är för att skydda eventuella multibytes i inmatningen – även om alla multibyte-versaler inte kommer att konverteras. Detsamma gäller för (GNU) tr
– båda apparna är benägna att mata in i alla länder som inte är C. iconv
kan kombineras med antingen för en heltäckande lösning.
2>/dev/null
omdirigerar dd
”standardstatusrapport – och dess stderr. Utan den dd
skulle följa slutförandet av ett jobb som ovan med utskriftsinformation som hur många byte som bearbetades osv.
Kommentarer
- Denna lösning är mycket snabbare än
tr
när du hanterar stora filer tack!
Svar
Du kan också använda Perl 5:
perl -pe "$_=lc" temp
Alternativet -p
berättar perl för att köra det angivna uttrycket en gång för varje inmatningsrad och skriva ut resultatet, dvs. det slutliga värdet av $_
. -e
indikerar att programmet blir nästa argument, till skillnad från en fil som innehåller skriptet. lc
konverterar till gemener. Utan argument fungerar det på $_
. Och $_=
sparar det igen så att det skrivs ut.
En variant av det skulle vara
perl -ne "print lc" temp
Använd -n
är som -p
förutom att $_
inte kommer att skrivas ut till slut. Så istället för att spara till den variabeln inkluderar jag ett uttryckligt utskriftsuttalande.
En fördel med Perl till skillnad från sed är att du inte behöver några GNU-tillägg. Det finns projekt som måste vara kompatibla med miljöer som inte är GNU men som också redan har Perl a s a dependency. Jämfört med tr
kan det vara så att Perl lc
lättare kan göras lokalmedveten. Se perllocale
mansidan för mer information.
Svar
Du måste fånga det matchade mönstret och använd det i stället för en modifierare:
sed "s/\([A-Z]\)/\L\1/g" temp
\(...\)
”fångar” omsluter matchad text, den första fångsten går till \1
, nästa till \2
osv. Numreringen är enligt öppningsfästen i händelse av kapslade fångster.
\L
konverterar det fångade mönstret till gemener, det finns också \U
.
Kommentarer
- du behöver inte göra detta – hela mönstret fångas alltid i
&
- Det är sant, men då skulle jag ha missat chansen att förklara att fånga matchningar 🙂
Svar
Utöver MvG: s svar kan du också använda Perl 6:
perl6 -pe .=lc temp
Här är $ _ implicit, och du behöver inte de enskilda offerten för att skydda den från expansion genom skalet ($ _ är en speciell Bash-parameter; se: https://www.gnu.org/software/bash/manual/html_node/Special-Parameters.html )