Dr Jay
Dr Jay

Reputation: 425

print first 3 characters and / rest of the string with stars

I'have this input like this

John:boofoo

I want to print rest of the string with stars and keep only 3 characters of the string.

The output will be like this

John:boo***

this my command

awk -F ":" '{print $1,$2 ":***"}'

I want to use only print command if possible. Thanks

Upvotes: 1

Views: 1396

Answers (9)

gniourf_gniourf
gniourf_gniourf

Reputation: 46853

Another pure Bash, using the builtin regular expression predicate.

input="John:boofoo"
if [[ $input =~ ^([^:]*:...)(.*)$ ]]; then
    printf '%s%s\n' "${BASH_REMATCH[1]}" "${BASH_REMATCH[2]//?/*}"
else
    echo >&2 "String doesn't match pattern"
fi

We split the string in two parts: the first part being everything up to (and including) the three chars found after the first colon (stored in ${BASH_REMATCH[1]}), the second part being the remaining part of string (stored in ${BASH_REMATCH[2]}). If the string doesn't match this pattern, we just insult the user.

We then print the first part unchanged, and the second part with every character replaced with *.

Upvotes: 0

Akshay Hegde
Akshay Hegde

Reputation: 16997

Some more awk

awk 'BEGIN{FS=OFS=":"}{s=sprintf("%0*d",length(substr($2,4)),0); gsub(/0/,"*",s);print $1,substr($2,1,3) s}' infile

You can use the %* form of printf, which accepts a variable width. And, if you use '0' as your value to print, combined with the right-aligned text that's zero padded on the left..

Better Readable:

awk 'BEGIN{
       FS=OFS=":"
     }
     {
       s=sprintf("%0*d",length(substr($2,4)),0); 
       gsub(/0/,"*",s);
       print $1,substr($2,1,3) s
     }
     ' infile

Test Results:

$ awk --version
GNU Awk 3.1.7
Copyright (C) 1989, 1991-2009 Free Software Foundation.

$ cat f
John:boofoo

$ awk 'BEGIN{FS=OFS=":"}{s=sprintf("%0*d",length(substr($2,4)),0); gsub(/0/,"*",s);print $1,substr($2,1,3) s}' f
John:boo***

Upvotes: 0

ctac_
ctac_

Reputation: 2491

Another sed : replace all chars after the third by *

sed -E ':A;s/([^:]*:...)(.*)[^*]([*]*)/\1\2\3*/;tA'

Upvotes: 0

Ed Morton
Ed Morton

Reputation: 204015

With GNU awk for gensub():

$ awk 'BEGIN{FS=OFS=":"} {print $1, substr($2,1,3) gensub(/./,"*","g",substr($2,4))}' file
John:boo***

With any awk:

awk 'BEGIN{FS=OFS=":"} {tl=substr($2,4); gsub(/./,"*",tl); print $1, substr($2,1,3) tl}' file
John:boo***

Upvotes: 1

Lars Fischer
Lars Fischer

Reputation: 10189

Since we have the tags awk, bash and sed: for completeness sake here is a bash only solution:

INPUT="John:boofoo"
printf "%s:%s\n" ${INPUT%%:*} $(TMP1=${INPUT#*:};TMP2=${TMP1:3}; echo "${TMP1:0:3}${TMP2//?/*}")

It uses two arguments to printf after the format string. The first one is INPUT stripped of by everything uncluding and after the :. Lets break down the second argument $(TMP1=${INPUT#*:};TMP2=${TMP1:3}; echo "${TMP1:0:3}${TMP2//?/*}"):

  • $(...) the string is interpreted as a bash command its output is substituted as last argument to printf
    • TMP1=${INPUT#*:}; remove everything up to and including the :, store the string in TMP1.
    • TMP2=${TMP1:3}; geht all characters of TMP1 from offset 3 to the end and store them in TMP2.
    • echo "${TMP1:0:3}${TMP2//?/*}" output the temporary strings: the first three chars from TMP1 unmodified and all chars from TMP2 as *
    • the output of the last echo is the last argument to printf

Here is the bash -x output:

+ INPUT=John:boofoo
++ TMP1=boofoo
++ TMP2=foo
++ echo 'boo***'
+ printf '%s:%s\n' John 'boo***'
John:boo***

Upvotes: 0

RavinderSingh13
RavinderSingh13

Reputation: 133640

Could you please try following. This will print stars(keeping only first 3 letters same as it is) how many characters are present in 2nd field after first 3 characters.

awk '
BEGIN{
  FS=OFS=":"
}
{
  stars=""
  val=substr($2,1,3)
  for(i=4;i<=length($2);i++){
    stars=stars"*"
  }
  $2=val stars
}
1
'  Input_file

Output will be as follows.

John:boo***

Explanation: Adding explanation for above code too here.

awk '
BEGIN{                          ##Starting BEGIN section from here.
  FS=OFS=":"                    ##Setting FS and OFS value as : here.
}                               ##Closing block of BEGIN section here.
{                               ##Here starts main block of awk program.
  stars=""                      ##Nullifying variable stars here.
  val=substr($2,1,3)            ##Creating variable val whose value is 1st 3 letters of 2nd field.
  for(i=4;i<=length($2);i++){   ##Starting a for loop from 4(becasue we need to have from 4th character to till last in 2nd field) till length of 2nd field.
    stars=stars"*"              ##Keep concatenating stars variable to its own value with *.
  }
  $2=val stars                  ##Assigning value of variable val and stars to 2nd field here.
}
1                               ##Mentioning 1 here to print edited/non-edited lines for Input_file here.
' Input_file                    ##Mentioning Input_file name here.

Upvotes: 0

anubhava
anubhava

Reputation: 785611

Another awk variant:

awk -F ":" '{print $1 FS substr($2, 1, 3) "***"}' <<< 'John:boofoo'

John:boo***

Upvotes: 0

David C. Rankin
David C. Rankin

Reputation: 84579

Or even with good old sed

$ echo "John:boofoo" | sed 's/...$/***/'

Output:

John:boo***

(note: this just replaces the last 3 characters of any string with "***", so if you need to key off the ':', see the GNU sed answer from Cyrus.)

Upvotes: 0

Cyrus
Cyrus

Reputation: 88776

With GNU sed:

echo 'John:boofoo' | sed -E 's/(:...).*/\1***/'

Output:

John:boo***

Upvotes: 2

Related Questions