Bash usuwa pierwszy i ostatni znak z ciągu

98

Mam taki ciąg:

|abcdefg|

I chcę uzyskać nowy ciąg wywoływany w jakiś sposób (np. Ciąg 2) z oryginalnym ciągiem bez dwóch |znaków na początku i na końcu, aby mieć to:

abcdefg

Czy to możliwe w bash?

Matteo Pagliazzi
źródło

Odpowiedzi:

120

Możesz to zrobić

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

Lub jeśli twoja długość łańcucha jest stała, możesz to zrobić

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

To też powinno działać

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

Także to

echo "|abcdefg|" | sed 's/^|\(.*\)|$/\1/'
Kris Harper
źródło
2
a takżeawk -F\| '{ print $2 }' <<<"|string|"
enzotib,
1
@enzotib Zawsze masz fajne awkrozwiązania. Muszę się nauczyć awk.
Kris Harper
3
a także IFS='|' read string2 <<< $string:)
umów się
10
a także w wersji bash 4.2 i nowszych"${string:1:-1}"
geirha,
Przeczytaj w sekcji „rozszerzenie parametru” w man bash.
Nemo,
62

Oto rozwiązanie niezależne od długości łańcucha (bash):

string="|abcdefg|"
echo "${string:1:${#string}-2}"
Samus_
źródło
29

Zejście z kilku wymienionych tutaj postów wydaje się najprostszym sposobem, aby to zrobić:

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

edycja: działa na ubuntu z bash 4.2; nie działa na centOS z bash 4.1

jlunavtgrad
źródło
19

Innym sposobem jest użycie poleceń headi tailpoleceń:

$ echo -n "|abcdefg|" | tail -c +2 | head -c -2
abcdefg
Zavior
źródło
1
Miałem ciąg [something something]z celem wycinania nawiasów, więc echo "[something something]" | tail -c +2 | head -c -2wypracowałem. Dzięki za wskazówkę!
Ain Tohvri,
Oczywiście tak powinno być echo -n "|abcdefg|" | tail -c +2 | head -c -1. Nie jestem pewien, dlaczego moje zmiany zostały odrzucone ... Szczerze mówiąc, to bardzo smutne. Zobacz man headwięcej informacji
Dmitrij Chamitow
10

I kolejny:

string="|abcdefg|"
echo "${string//|/}"
Steven Penny
źródło
9

Możesz także użyć sed, aby usunąć | nie tylko odwołując się do samego symbolu, ale także używając odniesień pozycyjnych jak w:

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

Gdzie „:” są ogranicznikami (możesz je zastąpić / lub dowolnym znakiem spoza zapytania, zrobi to dowolny znak następujący po s) Tutaj ^ (karetka) oznacza na początku ciągu wejściowego, a $ (dolar) oznacza na końcu. The. (punkt), że jest po karetce, a ten, który jest przed znakiem dolara reprezentuje pojedynczy znak. Innymi słowy, usuwamy pierwszy i ostatni znak. Pamiętaj, że spowoduje to usunięcie dowolnych znaków, nawet jeśli | nie jest obecny w ciągu.

DAWNY:

$ echo "abcdefg" | sed 's:^.\(.*\).$:\1:'
bcdef
Metafaniel
źródło
3

funkcja powłoki

Trochę bardziej szczegółowe podejście, ale działa na każdym rodzaju pierwszej i ostatniej postaci, nie musi być takie samo. Podstawową ideą jest to, że bierzemy zmienną, odczytujemy ją znak po znaku i dodajemy tylko te, które chcemy do nowej zmiennej

Oto cały ten pomysł sformatowany w przyjemną funkcję

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 
}

A oto ta sama funkcja w akcji:

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

Pyton

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

lub w wierszu poleceń:

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

AWK

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

Rubin

$ ruby -ne 'print $_.split("|")[1]' <<< "|abcdefg|"                                                               
abcdefg
Sergiy Kolodyazhnyy
źródło
2

Małe i uniwersalne rozwiązanie:

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

Specjalne w tym przypadku i pozwalające, aby „|” postać może tam być lub nie:

expr "|abcdef" : '|*\([^|]*\)|*'
Tosi Do
źródło
2
$ string="|abcdefg|"
$ string="${string#?}" && string="${string%%?}"
$ echo "$string"
abcdefg

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

${var#Pattern}
Usuń z $vartej najkrótszej części $Pattern, która odpowiada przód z $var. Usuń z tej najdłuższej części , która odpowiada tylny koniec z .
${var%%Pattern}
$var$Pattern$var

Brian
źródło