Jeg har temp
-fil med noget små og store bogstaver.
Input
Indholdet af min temp
fil:
hi Jigar GANDHI jiga
Jeg vil konvertere alle øvre til nedre .
Kommando
Jeg prøvede følgende kommando:
sed -e "s/[A-Z]/[a-z]/g" temp
men fik forkert output.
Output
Jeg vil have det som:
hi jigar gandhi jiga
Hvad skal der være i erstatning delen af argument for sed
?
Kommentarer
- Se også Hvordan konverteres UTF-8 txt-filer til store bogstaver i bash?
Svar
Hvis din input kun indeholder ASCII-tegn, kan du bruge tr
som:
eller (mindre let at huske og skrive IMO; men ikke begrænset til ASCII latinske bogstaver, dog i nogle implementeringer inklusive GNU tr
, stadig begrænset til enkeltbyte-tegn, så i UTF-8-lokaliteter, stadig begrænset til ASCII-bogstaver):
tr "[:upper:]" "[:lower:]" < input
hvis du skal bruge sed
:
sed "s/.*/\L&/g" < input
(her forudsat GNU-implementering).
Med POSIX sed
skal du angive alle translitterationer, og derefter kan du vælge hvilken bogstaver, du vil konvertere:
sed "y/AǼBCΓDEFGH.../aǽbcγdefgh.../" < input
Med awk
:
awk "{print tolower($0)}" < input
Kommentarer
- Bemærk, at
\L
er en GNU-udvidelse. -
\L
fungerer hidtil godt for mig. En lys det punkt, du prøver at lave GNU-udvidelse - @JigarGandhi.
sed
er en Unix-kommando. Forskellige systemer har forskellige varianter med forskellig opførsel og d funktionalitet. Heldigvis er der i dag ‘ en standard, der passer mest til, så du kan stole på et minimum af funktioner, der er fælles for alle.\L
er ikke blandt dem og blev introduceret af GNUsed
(matcher den samme operator i standardex
/vi
) og er generelt ikke tilgængelig i andre implementeringer. - Bemærk, at nogle
tr
implementeringer som GNUtr
don ‘ t fungerer korrekt i multi-byte-lokaliteter (de fleste af dem er i dag, prøvecho STÉPHANE | tr '[:upper:]' '[:lower:]'
for eksempel). På GNU-systemer foretrækker du muligvissed
-varianten ellerawk
‘ stolower()
. - Let korrektion:
sed 's/.*/\L&/g' < input
.\1
henvisningen til den matchede understreng vandt ‘ t, medmindre du angiver understrengen med parentes, som wurtle gør i sin. Det er dog ‘ lidt renere at bruge&
til at repræsentere hele kampen, som vist
Svar
Ved hjælp af vim er det super simpelt:
$ vim filename gg0guGZZ
Åbner filen gg
går til første linje, 0
, første kolonne. Med guG
, sænker tilfældet med alle tegn, indtil bunden af filen. ZZ
gemmer og afsluttes.
Det skal håndtere næsten alt, hvad du kaster på det; det “ll ignorerer tal, det” håndterer ikke ASCII.
Hvis du vil gøre det modsatte, skal du dreje de små bogstaver til store bogstaver, bytte u
ud for en U
: gg0gUGZZ
og du er indstillet.
Kommentarer
- Lol ” super simpelt ”
- dette
t skaler godt for mange filer
vim file1 file2 fileetc
og så ville noget som :bufdo gg0guG:w<CR>
sandsynligvis arbejde for et vilkårligt antal filer. Har dog ikke testet det! Svar
Jeg kan godt lide dd
til dette selv.
<<\IN LC_ALL=C 2<>/dev/null \ dd conv=lcase hi Jigar GANDHI jiga IN
… får …
hi jigar ghandi jiga
LC_ALL=C
er for at beskytte multibytes i input – selvom multibyte-hovedstæder ikke konverteres. Det samme gælder for (GNU) tr
– begge apps er tilbøjelige til at indtaste mangler i ethvert ikke-C-land. iconv
kan kombineres med enten til en omfattende løsning.
2>/dev/null
omdirigeringen kasserer dd
“s standardstatusrapport – og dens stderr. Uden den dd
ville følge færdiggørelsen af et job som ovenstående m / udskrivningsoplysninger som hvor mange byte der blev behandlet osv.
Kommentarer
- Denne løsning er langt hurtigere end
tr
når du håndterer store filer, tak!
Svar
Du kan også bruge Perl 5:
perl -pe "$_=lc" temp
Indstillingen -p
fortæller perl for at køre det angivne udtryk en gang for hver linie med input og udskrive resultatet, dvs. den endelige værdi af $_
. -e
angiver, at programmet bliver det næste argument i modsætning til en fil, der indeholder scriptet. lc
konverterer til små bogstaver. Uden et argument fungerer det på $_
. Og $_=
gemmer det igen, så det bliver udskrevet.
En variation af det ville være
perl -ne "print lc" temp
Brug af -n
er som -p
bortset fra at $_
ikke bliver udskrevet i sidste ende. Så i stedet for at gemme i denne variabel inkluderer jeg en eksplicit udskriftserklæring.
En fordel ved Perl i modsætning til sed er, at du ikke har brug for nogen GNU-udvidelser. Der er projekter, der skal være kompatible med miljøer, der ikke er GNU, men som også allerede har Perl en afhængighed. Sammenlignet med tr
kan det være, at Perl lc
lettere kan gøres lokalbevidst. Se perllocale
man-siden for detaljer.
Svar
Du skal fange det matchede mønster, og brug det derefter til erstatning med en modifikator:
sed "s/\([A-Z]\)/\L\1/g" temp
\(...\)
“fanger” omslutter matchet tekst, den første optagelse går til \1
, den næste til \2
osv. Nummereringen er i henhold til åbningsbeslag i tilfælde af nestede optagelser.
\L
konverterer det fangede mønster til små bogstaver, der er også \U
til store bogstaver .
Kommentarer
- du behøver ikke gøre dette – hele mønsteret er altid fanget i
&
- Sandt, men så ville jeg have gået glip af muligheden for at forklare fangstkampe 🙂
Svar
Ud over MvGs svar kan du også bruge Perl 6:
perl6 -pe .=lc temp
Her er $ _ implicit, og du behøver ikke de enkelte anførselstegn for at beskytte det mod udvidelse af skallen ($ _ er en speciel Bash-parameter; se: https://www.gnu.org/software/bash/manual/html_node/Special-Parameters.html )