4

I have a file.txt and each line of the file is like:

ABLED   EY B AH L D
ABLER   EY B AH L ER

I want to have the second part of each line: EY B AH L D or EY B AH L ER, for example, in lower case, keeping the rest upper case. How can I do it?

Thank you very much in advance.

6 Answers 6

8
while read first second; do
    second=$(echo "$second" | tr [:upper:] [:lower:])
    printf '%s\t%s\n' "$first" "$second"
done < file.txt

Output:

ABLED   ey b ah l d
ABLER   ey b ah l er

Two other ways to do it in KornShell, pdksh, or Bash without calling tr

set the "lowercase" flag on the variable (KornShell and compatible shells only):

typeset -l second
while read first second; do
    printf '%s\t%s\n' "$first" "$second"
done < file.txt

use Bash's case-modification parameter expansion modifier (Bash only!):

while read first second; do
    printf '%s\t%s\n' "$first" "${second,,}"
done < file.txt
3
  • @glennjackman Nice. I like both of your solutions better than mine. I didn't know about either of those features! Commented Dec 18, 2012 at 15:41
  • Neither declare, nor the ${,,} expansion modifier are standard POSIX sh features. In KornShell the equivalent to the former is available, but it's done with the built-in command typeset. typeset -l also works in pdksh, and Bash. So, always use typeset and never use declare. The case modification expansion modifiers are extensions unique (so far) to Bash. Commented Dec 18, 2012 at 20:04
  • Also, <<< is a KornShell and Bash extension not available in POSIX sh. Commented Dec 18, 2012 at 20:09
1

It can be done with sed using the following incredibly obfuscated script:

sed -e 'h;s/ .*//;x;s/[^ ]* //;y/AZERTYUIOPQSDFGHJKLMWXCVBN/azertyuiopqsdfghjklmwxcvbn/;H;x;s/\n/ /' your_file

Explained:

The first part of the script (h;s/ .*//;x;s/[^ ]* //) puts the part a the line before the 1st space in the hold space and the part of the line after the 1st space in the pattern space:

  • h: copies the actual line in the hold space.
  • s/ .*//: keeps in the pattern space only characters before the 1st space.
  • x: switch hold and pattern space.
  • s/[^ ]* //: keeps in the pattern space only characters after the 1st space.

Ok, now we have the 1st part of the line in the hold space, and the 2nd in the pattern space. We need to put the 2nd part in lower case, so we use y/AZERTYUIOPQSDFGHJKLMWXCVBN/azertyuiopqsdfghjklmwxcvbn/ (yes, I have an AZERTY keyboard).

Then, it is only a matter of getting back the 1st and 2nd part of the files together:

  • H: append pattern space to hold space.
  • x: exchange pattern space and hold space.
  • s/\n/ /: replace the \n of the H command by a space.

I hope you are not to disgusted by sed synthax ;-).

0

If you know your file will not change while reading it, and using bash:

paste -d " " <(cut -d " " -f 1 your_file) <(cut -d " " -f 2- your_file | tr "[:upper:]" "[:lower:]")
0

If you want a solution working with pipes (not the paste solution) and easier to understand than the sed solution, this is a solution with awk:

awk -F "[ ]" '{str=$1;$1="";print str tolower($0)}' your_file

The field separator cannot simply be " " as consecutive spaces are in this case considered as a single separator.

0

Please use #!/bin/ksh in the begining of the script even if you want it to run it in Linux platform. This ksh accepts all kind of typeset variables that we use in HpUx or Solaris.

1
  • It is not clear why you answered the question in this way. Did you read it at all? Please read carefully!
    – Trinimon
    Commented Apr 11, 2013 at 11:22
-1

A Python script:

import sys
for l in sys.stdin.read().splitlines():
    try:
        head,rest = l.split(' ', 1)
        print head, rest.lower()
    except: print l

Run it like this (assuming you save the script in a file called filter.py):

$ python filter.py < file.txt

Not the answer you're looking for? Browse other questions tagged or ask your own question.