Jeg har temp
-fil med noe små og store bokstaver.
Inngang
Innholdet i temp
-filen:
hi Jigar GANDHI jiga
Jeg vil konvertere alle øvre til nedre .
Kommando
Jeg prøvde følgende kommando:
sed -e "s/[A-Z]/[a-z]/g" temp
men fikk feil utgang.
Utgang
Jeg vil ha det som:
hi jigar gandhi jiga
Hva som må være i erstatning delen argument for sed
?
Kommentarer
- Se også Hvordan konvertere UTF-8 txt-filer til store bokstaver i bash?
Svar
Hvis innspillene bare inneholder ASCII-tegn, kan du bruke tr
som:
eller (mindre lett å huske og skrive IMO; men ikke begrenset til ASCII latinske bokstaver, men i noen implementeringer inkludert GNU tr
, fremdeles begrenset til enkeltbyte-tegn, så i UTF-8 lokaliteter, fremdeles begrenset til ASCII-bokstaver):
tr "[:upper:]" "[:lower:]" < input
hvis du må bruke sed
:
sed "s/.*/\L&/g" < input
(her forutsatt GNU-implementeringen).
Med POSIX sed
, trenger du å spesifisere alle translitterasjonene, og deretter kan du velge hvilken bokstaver du vil konvertere:
sed "y/AǼBCΓDEFGH.../aǽbcγdefgh.../" < input
Med awk
:
awk "{print tolower($0)}" < input
Kommentarer
- Vær oppmerksom på at
\L
er en GNU-utvidelse. -
\L
fungerer bra for meg så langt. En lys det punktet at du prøver å lage GNU-utvidelse - @JigarGandhi.
sed
er en Unix-kommando. Ulike systemer har forskjellige varianter med ulik oppførsel og d funksjonalitet. Heldigvis er det i dag ‘ en standard som passer mest, slik at du kan stole på et minimum sett med funksjoner som er felles for alle.\L
er ikke blant dem og ble introdusert av GNUsed
(samsvarer med samme operator i standardex
/vi
) og er vanligvis ikke tilgjengelig i andre implementeringer. - Merk at noen
tr
implementeringer som GNUtr
ikke ‘ t fungerer ordentlig på flere byte-steder (de fleste av dem er i dag, prøvecho STÉPHANE | tr '[:upper:]' '[:lower:]'
for eksempel). På GNU-systemer foretrekker du kanskjesed
-varianten ellerawk
‘ stolower()
. - Lett korreksjon:
sed 's/.*/\L&/g' < input
.\1
referansen til den matchede understrengen vant ‘ t, med mindre du spesifiserer understrengen med parentes slik wurtle gjør i sin. Det er imidlertid ‘ litt renere å bruke&
for å representere hele kampen, som vist
Svar
Ved hjelp av vim er det superenkelt:
$ vim filename gg0guGZZ
Åpner filen, gg
går til første linje, 0
, første kolonne. Med guG
, senker saken til alle tegnene til bunnen av filen. ZZ
lagrer og går ut.
Den skal håndtere omtrent alt du kaster på den; den «vil ignorere tall, det» vil håndtere ikke ASCII.
Hvis du ville gjøre det motsatte, snu de små bokstavene til store bokstaver, bytt u
ut for en U
: gg0gUGZZ
og du er klar.
Kommentarer
- Lol » superenkelt »
- dette gjør åpenbart ikke ‘ t skalere godt for mange filer
- @CoreyGoldberg
vim file1 file2 fileetc
og da ville noe sånt som:bufdo gg0guG:w<CR>
sannsynligvis / i> arbeid for et hvilket som helst antall filer. Har ikke testet det skjønt! - @TankorSmash som fremdeles ikke ‘ t skalerer til et stort antall filer
Svar
Jeg liker dd
for dette selv.
<<\IN LC_ALL=C 2<>/dev/null \ dd conv=lcase hi Jigar GANDHI jiga IN
… blir …
hi jigar ghandi jiga
LC_ALL=C
er for å beskytte alle multibytes i inngangen – selv om multibytehovedsteder ikke blir konvertert. Det samme gjelder (GNU) tr
– begge appene er tilbøyelige til å legge inn mangler i alle ikke-C-land. iconv
kan kombineres med enten for en omfattende løsning.
2>/dev/null
omdirigering forkaster dd
«s standardstatusrapport – og dens stderr. Uten den dd
vil følge gjennomføring av en jobb som ovenfor med utskriftsinformasjon som hvor mange byte som ble behandlet og så videre.
Kommentarer
- Denne løsningen er mye raskere enn
tr
når du håndterer store filer, takk!
Svar
Du kan også bruke Perl 5:
perl -pe "$_=lc" temp
Alternativet -p
forteller perl for å kjøre det angitte uttrykket en gang for hver linje med inndata, og skrive ut resultatet, dvs. den endelige verdien av $_
. -e
indikerer at programmet blir neste argument, i motsetning til en fil som inneholder skriptet. lc
konverterer til små bokstaver. Uten argument vil det fungere på $_
. Og $_=
lagrer det igjen slik at det blir skrevet ut.
En variant av det ville være
perl -ne "print lc" temp
Bruk av -n
er som -p
bortsett fra at $_
ikke blir skrevet ut til slutt. Så i stedet for å lagre i den variabelen, inkluderer jeg en eksplisitt utskrift.
En fordel med Perl i motsetning til sed er at du ikke trenger noen GNU-utvidelser. Det er prosjekter som må være kompatible med miljøer som ikke er GNU, men som også allerede har en avhengighet av Perl. Sammenlignet med tr
, kan det være at Perl lc
lettere kan gjøres lokalbevisst. Se perllocale
man-siden for detaljer.
Svar
Du må fange det matchede mønsteret, og bruk det deretter til erstatning med en modifikator:
sed "s/\([A-Z]\)/\L\1/g" temp
\(...\)
«fanger» vedlegger samsvarende tekst, går den første opptaket til \1
, den neste til \2
osv. Nummereringen er i henhold til åpningsparenteser i tilfelle nestede opptak.
\L
konverterer det fangede mønsteret til små bokstaver, det er også \U
for store bokstaver .
Kommentarer
- du trenger ikke gjøre dette – hele mønsteret er alltid fanget i
&
- Sant, men da ville jeg ha gått glipp av muligheten til å forklare å fange kamper 🙂
Svar
I tillegg til MvGs svar kan du også bruke Perl 6:
perl6 -pe .=lc temp
Her er $ _ implisitt, og du trenger ikke de enkelte anførselstegnene for å beskytte den mot utvidelse av skallet ($ _ er en spesiell Bash-parameter; se: https://www.gnu.org/software/bash/manual/html_node/Special-Parameters.html )