help-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Help-bash] how to translate one file


From: Eric Blake
Subject: Re: [Help-bash] how to translate one file
Date: Tue, 03 Jan 2012 08:43:50 -0700
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:9.0) Gecko/20111222 Thunderbird/9.0

On 01/03/2012 08:15 AM, lina wrote:
> When I derive it to a field problem,
> 
> $ cat dm_1.xpm | while read line ; do IFS=$'\n' ; if [ ${#line} == 30 ];
> then echo $line ; fi ; done

Useless use of cat.  Use of $'\n', as well as == within [, are bash
extensions; there's talk of standardizing both of them in the next
version of POSIX, but they isn't portable yet.  I have no idea why you
are changing $IFS, nor why you forget to reset it later, as it doesn't
affect anything in your 2-line sample; but assuming it was important,
I'll keep it as you wrote it.  Also, you had insufficient quoting; you
probably want echo "$line" rather than echo $line.  I would have written
this as:

while read line; do
  IFS='
'
  if [ ${#line} = 30 ]; then
    echo "$line";
  fi
done < dm_1.xpm

> if I use:
> $ cat dm_1.xpm | while read line ; do IFS=$'\n' ; if [ ${#line} == 30 -a
> ${line:0:1}== '"' ]; then echo $line ; fi ; done
> bash: [: too many arguments

That's because you are invoking [ incorrectly - operators MUST be
separated by spaces, but since you joined ${line:0:1} and == as a single
argument, you ended up causing a syntax error.  Also, [ -a is not
portable; POSIX explicitly recommends against using it.  And ${line:0:1}
is a bash extension; you can portably get the same effect of comparing
the first byte via a case statement.  I think you either want to fix
your version:

cat dm_1.xpm | while read line ; do IFS=$'\n' ;
  if [ ${#line} == 30 -a ${line:0:1} == '"' ]; then echo $line ; fi ; done

or to use this portable alternative:

while read line; do
  if [ ${#line} = 30 ]; then
    case $line in \") echo "$line" ;; esac
  fi
done < dm_1.xpm

Or, do your entire processing in sed instead of a shell loop; this
script filters out and prints only lines which meet two simultaneous
regex - a line that starts with ", and a line that has exactly 30
characters:

sed -n '/^"/ { /^.\{30\}$/ p; }' dm_1.xpm

-- 
Eric Blake   address@hidden    +1-919-301-3266
Libvirt virtualization library http://libvirt.org

Attachment: signature.asc
Description: OpenPGP digital signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]