Bash remove first and last characters from a string

I have a string like that:

|abcdefg|

And I want to get a new string called in someway (like string2) with the original string without the two | characters at the start and at the end of it so that I will have this:

abcdefg

Is that possible in bash?

10 Answers

You can do

string="|abcdefg|"
string2=${string#"|"}
string2=${string2%"|"}
echo $string2

Or if your string length is constant, you can do

string="|abcdefg|"
string2=${string:1:7}
echo $string2

Also, this should work

echo "|abcdefg|" | cut -d "|" -f 2

Also this

echo "|abcdefg|" | sed 's/^|\(.*\)|$/\1/'
5

Here's a solution that is independent of the length of the string (bash):

string="|abcdefg|"
echo "${string:1:${#string}-2}"

Going off a few posts listed here it seems the simplest way to do it is:

string="|abcdefg|"
echo ${string:1:-1}

edit: works on ubuntu with bash 4.2; does not work on centOS with bash 4.1

2

Another way is to use head & tail commands:

$ echo -n "|abcdefg|" | tail -c +2 | head -c -2
abcdefg
2

You can also use sed to remove the | not just referencing the symbol itself but using positional references as in:

$ echo "|abcdefg|" | sed 's:^.\(.*\).$:\1:'
abcdefg

Where ':' are the delimiters (you can replace them with / or any character not in the query, any sign following the s will do it) Here ^ (caret) means at the beginning of the input string and $ (dollar) means at the end. The . (point) that it's after the caret and the one that it's before the dollar sign represents a single character. So in other words we are deleting the first and last characters. Take in mind this will delete any characters even if | it's not present in the string.

EX:

$ echo "abcdefg" | sed 's:^.\(.*\).$:\1:'
bcdef

And another one:

string="|abcdefg|"
echo "${string//|/}"

shell function

A bit more verbose approach, but works on any sort of first and last character, doesn't have to be the same. Basic idea is that we are taking a variable, reading it character by character, and appending only those we want to a new variable

Here's that whole idea formatted into a nice function

crop_string_ends() { STR="$1" NEWSTR="" COUNT=0 while read -n 1 CHAR do COUNT=$(($COUNT+1)) if [ $COUNT -eq 1 ] || [ $COUNT -eq ${#STR} ] then continue fi NEWSTR="$NEWSTR"$CHAR done <<<"$STR" echo $NEWSTR
}

And here is that same function in action:

$> crop_string_ends "|abcdefg|"
abcdefg
$> crop_string_ends "HelloWorld"
elloWorl

Python

>>> mystring="|abcdefg|"
>>> print(mystring[1:-1])
abcdefg

or on command line:

$ python -c 'import sys;print sys.stdin.read()[1:-2]' <<< "|abcdefg|"
abcdefg

AWK

$ echo "|abcdefg|" | awk '{print substr($0,2,length($0)-2)}'
abcdefg

Ruby

$ ruby -ne 'print $_.split("|")[1]' <<< "|abcdefg|"
abcdefg

Small and universal solution:

expr "|abcdef|" : '.\(.*\).'

Special in this case and allowing that the '|' character may be there or not:

expr "|abcdef" : '|*\([^|]*\)|*'
$ string="|abcdefg|"
$ string="${string#?}" && string="${string%%?}"
$ echo "$string"
abcdefg

From

${var#Pattern}
Remove from $var the shortest part of $Pattern that matches the front end of $var.
${var%%Pattern}
Remove from $var the longest part of $Pattern that matches the back end of $var.

You can use this:

echo "|abcdefg|" | tr -d "|"

With this line of code, you remove all |->(pipe) in the string.

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

You Might Also Like