98

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?

120

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/'
  • 2
    and also awk -F\| '{ print $2 }' <<<"|string|" – enzotib Dec 23 '11 at 17:45
  • 1
    @enzotib You always have cool awk solutions. I need to learn awk. – Kris Harper Dec 23 '11 at 18:36
  • 3
    and also IFS='|' read string2 <<< $string :) – arrange Dec 23 '11 at 20:38
  • 10
    and also, in bash 4.2 and newer, "${string:1:-1}" – geirha Jul 5 '12 at 12:52
  • Read under the "parameter expansion" section in man bash. – Nemo Sep 5 '12 at 20:44
62

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

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

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

19

Another way is to use head & tail commands:

$ echo -n "|abcdefg|" | tail -c +2 | head -c -2
abcdefg
  • 1
    I had a string of [something something] with a goal to cut brackets, so echo "[something something]" | tail -c +2 | head -c -2 worked out. Thanks for a tip! – Ain Tohvri Dec 13 '15 at 15:36
  • Obviously, it should be echo -n "|abcdefg|" | tail -c +2 | head -c -1. I'm not sure why my edits were rejected... It's very sad, to be honest. See man head for more info – Dmitry Khamitov Mar 27 at 13:11
10

And another one:

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

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
3

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
2

Small and universal solution:

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

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

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

From http://tldp.org/LDP/abs/html/parameter-substitution.html

${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.

Your Answer

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

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