Bash elimina el primer y último carácter de una cadena

100

Tengo una cadena como esa:

|abcdefg|

Y quiero obtener una nueva cadena llamada de alguna manera (como string2) con la cadena original sin los dos |caracteres al principio y al final para que tenga esto:

abcdefg

¿Es eso posible en bash?

Matteo Pagliazzi
fuente

Respuestas:

121

Tu puedes hacer

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

O si la longitud de su cadena es constante, puede hacer

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

Además, esto debería funcionar

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

También esto

echo "|abcdefg|" | sed 's/^|\(.*\)|$/\1/'
Kris Harper
fuente
2
y tambiénawk -F\| '{ print $2 }' <<<"|string|"
enzotib
1
@enzotib Siempre tienes awksoluciones geniales . Necesito aprender awk.
Kris Harper
3
y también IFS='|' read string2 <<< $string:)
organizar el
10
y también, en bash 4.2 y más reciente,"${string:1:-1}"
geirha
Lea en la sección "expansión de parámetros" en man bash.
Nemo
63

Aquí hay una solución que es independiente de la longitud de la cadena (bash):

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

Saliendo de algunas publicaciones enumeradas aquí, parece que la forma más sencilla de hacerlo es:

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

editar: funciona en ubuntu con bash 4.2; no funciona en centOS con bash 4.1

jlunavtgrad
fuente
21

Otra forma es usar heady tailcomandos:

$ echo -n "|abcdefg|" | tail -c +2 | head -c -2
abcdefg
Comportamiento
fuente
1
Tenía una serie de [something something]objetivos para cortar los corchetes, así que echo "[something something]" | tail -c +2 | head -c -2funcionó. Gracias por un consejo!
Ain Tohvri
Obviamente, debería ser echo -n "|abcdefg|" | tail -c +2 | head -c -1. No estoy seguro de por qué mis ediciones fueron rechazadas ... Es muy triste, para ser honesto. Ver man headpara más información
Dmitry Khamitov
10

Y otro:

string="|abcdefg|"
echo "${string//|/}"
Steven Penny
fuente
9

También puede usar sed para eliminar el | no solo haciendo referencia al símbolo en sí, sino usando referencias posicionales como en:

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

Donde ':' son los delimitadores (puede reemplazarlos con / o cualquier carácter que no esté en la consulta, cualquier signo que siga al s lo hará) Aquí ^ (caret) significa al comienzo de la cadena de entrada y $ (dólar) significa al final. Los . (punto) que está después del símbolo de intercalación y el que está antes del signo de dólar representa un solo carácter. En otras palabras, estamos eliminando el primer y el último carácter. Tenga en cuenta que esto eliminará cualquier carácter incluso si | No está presente en la cadena.

EX:

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

función de shell

Un enfoque un poco más detallado, pero funciona en cualquier tipo de primer y último personaje, no tiene que ser el mismo. La idea básica es que estamos tomando una variable, leyéndola carácter por carácter y agregando solo aquellos que queremos a una nueva variable

Aquí está toda esa idea formateada en una buena función

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 
}

Y aquí está esa misma función en acción:

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

Pitón

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

o en la línea de comando:

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

AWK

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

Rubí

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

Solución pequeña y universal:

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

Especial en este caso y permitiendo que el '|' el personaje puede estar ahí o no:

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

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

${var#Pattern}
Eliminar de $varla parte más corta de $Patterneso coincide con el extremo frontal de $var. Eliminar de la parte más larga de eso coincide con el extremo posterior de .
${var%%Pattern}
$var$Pattern$var

Brian
fuente