Lowercase all but the first column
Matthew Barrera
How can I make all but the first column lower case?
like:
1 ONE
2 TWO TWO
3 THREE THREE THREErequired output:
1 one
2 two two
3 three three three 4 4 Answers
You could use GNU sed's lowercase \L extension:
sed -r 's/([^ \t]+\s)(.*)/\1\L\2/' fileExplanation
-ruse EREs/old/new/replaceoldwithnew([^ \t]+\s)save some characters that are not space or tab, followed by a space or tab(.*)save any number of any characters\1\L\2print the first saved part unchanged, then the second saved part lowercased
awk with iterating over all but the first field, and converting the strings to lowercase using tolower() function:
awk '{out=""; for (i=2; i<=NF; i++) out=out" "tolower($i); print $1out}' file.txtpaste, cut, and sed, with help from process substitution:
paste -d ' ' <(cut -d' ' -f1 file.txt) <(cut -d' ' -f2- file.txt | \ sed -E 's/([[:upper:]])/\L\1/g')This has the caveat of opening the file twice.
With only bash, using parameter expansion to convert cases:
while IFS=' ' read -r i j; do echo "${i} ${j,,}"; done <file.txtExample:
$ cat file.txt
1 ONE
2 TWO TWO
3 THREE THREE THREE
$ awk '{out=""; for (i=2; i<=NF; i++) out=out" "tolower($i); print $1out}' file.txt
1 one
2 two two
3 three three three
$ paste -d ' ' <(cut -d' ' -f1 file.txt) <(cut -d' ' -f2- file.txt | sed -E 's/([[:upper:]])/\L\1/g')
1 one
2 two two
3 three three three
$ while IFS=' ' read -r i j; do echo "${i} ${j,,}"; done <file.txt
1 one
2 two two
3 three three three 3 Perl approach with the use of lc() function:
$ perl -lne 'print lc($_)' < input.txt
1 one
2 two two
3 three three threePython approach:
$ python -c "import sys;print ''.join([l.lower() for l in sys.stdin])" < input.txt
1 one
2 two two
3 three three three- send input file as
stdinto the python command using<shell redirection - using
sysread all lines using list comprehension (thel for l in liststructure), while simultaneously using.lower()method - the resulting list of lines is joined into one string and printed out
If you want to remove trailing newline, you can do so by adding single comma at the end for Python 2 (which is default for python command ):
$ python -c "import sys;print ''.join([l.lower() for l in sys.stdin])," < input.txtFor Python 3, the print function is different, and it has different way of stripping trailing newline - via end keyword:
$ python3 -c "import sys;print(''.join([l.lower() for l in sys.stdin]),end='')" < input.txt Previous approaches assume that first column is numeric as in OP's example. For generic approach where we want only non-first columns to be converted, we can do this in perl:
$ cat input.txt
1 ONE
SOMETHING TWO TWO
$!@# THREE THREE THREE
$ perl -ane 'print $F[0]; print map { " " . lc($_)} @F[1..$#F];print "\n"' < input.txt
1 one
SOMETHING two two
$!@# three three threeIn python for the sake of readability, we can do a script:
#!/usr/bin/env python
import sys
for line in sys.stdin: words = line.strip().split() case_words = [ word.lower() for word in words[1:] ] print( " ".join([words[0]]+case_words) )Which works like so with the same input as in perl example:
$ ./lowercase_columns.py < input.txt
1 one
SOMETHING two two
$!@# three three three 4 A late one:
Just for fun, another python approach:
python3 -c "for l in open('f'): l = l.split(' ',1); print(l[0], l[1].strip().lower())"Where 'f' is the file, between quotes.
This approach assumes the file does not have empty lines.
Explanation
Each of the lines is first split on the first occurrence of the delimiter.
l = l.split(' ',1)Subsequently, the second part (all columns but the first) is lowered:
l[1].strip().lower()and the combined result is printed:
print(l[0], l[1].strip().lower())
Example output
On a file:
EEN AAP OP EEN FIETS
2 EEn banaan IS LEKKER
MIJN tante in Marokko
1 ONE
2 TWO TWO
3 THREE THREE THREEThe output is:
EEN aap op een fiets
2 een banaan is lekker
MIJN tante in marokko
1 one
2 two two
3 three three three