Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I needed to remove spaces and capital letters to various strings of text like:

"My Name is Mauro" -> "my_name_is_mauro"

So I have created this bash script:lowercase_underscore.sh (call it the same for testing). Is there another way to accomplish this with a loop?

#!/bin/bash
echo "Please enter a word:
(leave blank and press Enter to exit)"

# read user input
read foobar

# exit
if [[ $foobar == '' ]]; then
    exit
fi

# convert upper case to lower
foobar=$(echo "$foobar" | tr '[:upper:]' '[:lower:]')

# strip underscore and apostrophe
foobar=${foobar// /_}
foobar=${foobar//\'/}

# output
echo "########
"

echo "machine_name_"${foobar}

echo "
########"

# loop - execute itself (this could go against the Three Laws of Robotics)
bash lowercase_underscore.sh
share|improve this question
1  
Is this homework? Why do you want to use a loop? –  jordanm Mar 6 at 5:45
    
It's perfectly fine to ask for guidance here if it is homework, just be honest and let ppl here know. –  slm Mar 6 at 5:57
    
@slm, jordanm, his previous questions appear to be fairly practical. I am giving him benefit of doubt ;-) –  1_CR Mar 6 at 6:01
    
@1_CR - as am I. –  slm Mar 6 at 6:03

3 Answers 3

#!/bin/bash -
while 
  echo "Please enter a word:
  (leave blank and press Enter to exit)"
  IFS= read -r foobar

  [ -n "$foobar" ]
do
  foobar=${foobar,,*}

  printf '%s\n' "${foobar// /_}"
done

POSIXly:

while 
  echo "Please enter a word:
  (leave blank and press Enter to exit)"
  IFS= read -r foobar

  [ -n "$foobar" ]
do
  printf '%s\n' "$foobar" | tr ' ' _ | tr '[:upper:]' '[:lower:]'
done

Or (as text processing is better done in a text processing utility, than a shell):

#! /usr/bin/awk -f
function prompt() {
  print "Please enter a word:\n(leave blank and press Enter to exit)"
}
BEGIN {prompt()}
$0 == "" {exit}
{gsub(" ", "_"); print tolower($0); prompt()}
share|improve this answer

I found these examples on SO in this Q&A titled: How to perform a for loop on each character in a string in BASH?.

Example #1 - destructive

Here's a script called onechar1.bash.

#!/bin/bash

echo "Please enter a word:
(leave blank and press Enter to exit)"
read someStr

if [[ $someStr == '' ]]; then
    exit
fi

while test -n "$someStr"; do
   c=${someStr:0:1}       # Get the first character
   echo "character is $c"
   someStr=${someStr:1}   # trim the first character
done

When I run it:

$ ./onechar1.bash 
Please enter a word:
(leave blank and press Enter to exit)
My Name is Mauro
character is M
character is y
character is  
character is N
character is a
character is m
character is e
character is  
character is i
character is s
character is  
character is M
character is a
character is u
character is r
character is o
$

Example #2 - non-destructive

Here's another script, onechar2.bash:

#!/bin/bash

echo "Please enter a word:
(leave blank and press Enter to exit)"
read someStr

if [[ $someStr == '' ]]; then
    exit
fi

for (( i=0; i<${#someStr}; i++ )); do
    echo ${someStr:$i:1}
done

When I run this script:

$ ./onechar2.bash 
Please enter a word:
(leave blank and press Enter to exit)
My Name is Mauro
M
y

N
a
m
e

i
s

M
a
u
r
o
$
share|improve this answer

Here's at least one Posix portable method that relies only on shell builtins (with the possible exception of printf), (Posix) parameter slicing and attempts to loop as little as possible:

lowerunder() { local c="${1%[A-Z ]*}" 
    set -- "$1" "$c" "${1#"$c"}"
    [ -z "$3" ] && printf %s "$1" || {            
        c="${3%"${3#?}"}"
        [ -z "${c#[ ]}" ] && c=_
        [ -z "${c#[A-Z]}" ] && { 
            c="$(printf %x "'$c")";
            c="$(printf %b "\x$((c+20))")" ; }
        lowerunder "${2}${c}${3#?}"
} ; }

Feed it one argument enclosed in quotes and it will replace the spaces within and all uppercase characters with lower.

Feed it two or more and it will still return your first argument converted all to lowercase and spaces converted underscores. It doesn't do a lot.

I confess I'm not good with hex math and that might be a weak point here - I use printf to convert from Ascii character code to hex value to decimal and back again. Still, it was fun to write.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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