Ik heb een variabele var
in een bash-script met een string, zoals:
echo $var
"some string.rtf"
Ik wil de laatste 4 tekens van deze tekenreeks verwijderen en het resultaat toewijzen aan een nieuwe variabele var2
, zodat
echo $var2
"some string"
Hoe kan ik dit doen?
1, Autoriteit 100%
Ten eerste is het meestal beter om expliciet te zijn over uw intentie. Dus als u weet dat de tekenreeks eindigt in .rtf
, en u wilt verwijderen die .rtf
, kunt u gewoon gebruiken var2=${var%.rtf}
. Eén potentieel bruikbaar aspect van deze aanpak is dat als de string niet eindigt eindigt in .rtf
, het is helemaal niet gewijzigd; var2
bevat een niet-gemodificeerde kopie van var
.
Als u een FileName-achtervoegsel wilt verwijderen, maar niet weet of u precies wilt weten wat het is, kunt u var2=${var%.*}
gebruiken om alles te verwijderen met de laatste .
. Of, als u alleen alles wilt houden, maar niet het .
, kunt u var2=${var%%.*}
. Die opties hebben hetzelfde resultaat als er maar één is .
, maar als er meer dan één is, kunt u kiezen welk einde van de tekenreeks te werken. Aan de andere kant, als er geen .
In de reeks helemaal, var2
wordt opnieuw een ongewijzigde kopie van var
.
Als u echt een specifiek van tekens van tekens wilt verwijderen, zijn hier enkele opties.
Je hebt deze bash
specifiek getagd, dus we beginnen met bash-ingebouwde elementen. Degene die het langst heeft gewerkt, is dezelfde syntaxis voor het verwijderen van achtervoegsels die ik hierboven heb gebruikt: om vier tekens te verwijderen, gebruik var2=${var%????}
. Of om alleen vier tekens te verwijderen als de eerste een punt is, gebruikt u var2=${var%.???}
, dat is als var2=${var%.*}
maar verwijdert alleen het achtervoegsel als het gedeelte na de punt precies drie tekens lang is. Zoals je kunt zien, moet je om tekens op deze manier te tellen één vraagteken per onbekend teken verwijderen, dus deze benadering wordt onpraktisch voor grotere subtekenreeksen.
Een optie in nieuwere shell-versies is extractie van substrings: var2=${var:0:${#var}-4}
. Hier kunt u een willekeurig getal in plaats van de 4
plaatsen om een ander aantal tekens te verwijderen. De ${#var}
wordt vervangen door de lengte van de tekenreeks, dus dit vraagt eigenlijk om het extraheren en behouden van (lengte – 4) tekens, beginnend met de eerste (bij index 0). Met deze benadering verliest u de optie om de wijziging alleen aan te brengen als de tekenreeks overeenkomt met een patroon; wat de werkelijke waarde van de tekenreeks ook is, de kopie bevat alle behalve de laatste vier tekens.
Je kunt de startindex weglaten; het is standaard 0, dus je kunt dat inkorten tot gewoon var2=${var::${#var}-4}
. In feite herkennen nieuwere versies van bash (met name 4+, wat betekent dat degene die met MacOS wordt geleverd niet zal werken) negatieve lengtes als de index van het teken om bij te stoppen, terugtellend vanaf het einde van de reeks. Dus in die versies kun je ook de tekenreekslengte-expressie verwijderen: var2=${var::-4}
.
Als je niet echt bash gebruikt maar een andere POSIX-type shell, zal de op patronen gebaseerde achtervoegselverwijdering met %
nog steeds werken – zelfs in een gewoon oud streepje, waar de op index gebaseerde substring extractie niet. Ksh en zsh ondersteunen beide substring-extractie, maar vereisen de expliciete 0-startindex; zsh ondersteunt ook de negatieve eindindex, terwijl ksh de lengte-expressie vereist. Merk op dat zsh, dat arraysindexeert vanaf 1, niettemin stringsindexeert vanaf 0 als je deze bash-compatibele syntaxisgebruikt. Maar met zsh kunt u ook scalaire parameters behandelen alsof het arrays van tekens zijn, in welk geval de syntaxis van de subtekenreeks een 1-gebaseerde telling gebruikt en de start- en (inclusief) eindposities tussen haakjes plaatst, gescheiden door komma’s: var2=$var[1,-5]
.
In plaats van de ingebouwde shell-parameteruitbreiding te gebruiken, kunt u natuurlijk een hulpprogramma uitvoeren om de tekenreeks te wijzigen en de uitvoer ervan vast te leggen met opdrachtvervanging. Er zijn verschillende commando’s die zullen werken; een daarvan is var2=$(sed 's/.\{4\}$//' <<<"$var")
.
Antwoord 2, autoriteit 95%
Je kunt het als volgt doen:
#!/bin/bash
v="some string.rtf"
v2=${v::-4}
echo "$v --> $v2"
Antwoord 3, autoriteit 91%
Gebruik ${var%????}
om vier tekens aan het einde van de tekenreeks te verwijderen.
Om alles te verwijderen na de laatste .
gebruik je ${var%.*}
.
Antwoord 4, autoriteit 90%
Wat voor mij werkte was:
echo "hello world" | rev | cut -c5- | rev
# hello w
Maar ik gebruikte het om lijnen in een bestand bij te snijden, dus daarom ziet het er onhandig uit. Het echte gebruik was:
cat somefile | rev | cut -c5- | rev
cut
brengt je alleen zo ver als het trimmen van een startpositie, wat slecht is als je rijen met variabele lengte nodig hebt. Dus deze oplossing keert (rev
) de string om en nu kunnen we betrekking hebben op zijn eindpositie, gebruikt dan cut
zoals vermeld, en keert (opnieuw, rev
) het terug naar zijn oorspronkelijke bestellen.
Antwoord 5, autoriteit 44%
Met behulp van Variabele uitbreiding/Substring vervanging:
${var/%Pattern/Replacement}
Als het achtervoegsel van var overeenkomt met Patroon, vervang dan Patroon door Vervanging.
Dus je kunt het volgende doen:
~$ echo ${var/%????/}
some string
Als alternatief,
Als je altijd dezelfde 4 letters hebt
~$ echo ${var/.rtf/}
some string
Als het altijd eindigt op .xyz
:
~$ echo ${var%.*}
some string
Je kunt ook de lengte van de string gebruiken:
~$ len=${#var}
~$ echo ${var::len-4}
some string
of gewoon echo ${var::-4}
Antwoord 6, autoriteit 36%
Je zou sed kunnen gebruiken,
sed 's/.\{4\}$//' <<< "$var"
Voorbeeld:
$ var="some string.rtf"
$ var1=$(sed 's/.\{4\}$//' <<< "$var")
$ echo $var1
some string
7, Autoriteit 5%
Ik heb het volgende geprobeerd en het werkte voor mij:
#! /bin/bash
var="hello.c"
length=${#var}
endindex=$(expr $length - 4)
echo ${var:0:$endindex}
Uitgang: hel
8, Autoriteit 5%
In dit geval zou u Basename kunnen gebruiken, ervan uitgaande dat u hetzelfde achtervoegsel hebt op de bestanden die u wilt verwijderen.
Voorbeeld:
basename -s .rtf "some string.rtf"
Hierdoor wordt “sommige tekenreeks”
terug
Als u het achtervoegsel niet kent, en wilt u alles verwijderen na en inclusief de laatste punt:
f=file.whateverthisis
basename "${f%.*}"
Uitgangen “Bestand”
% betekent hakken ,. is wat u hakt, * is jokerteken
9, Autoriteit 3%
Dit werkte voor mij door het berekenen van de grootte van de reeks.
Het is eenvoudig dat u de waarde wilt weergeven die u moet retourneren en vervolgens opslaan zoals hieronder
removechars(){
var="some string.rtf"
size=${#var}
echo ${var:0:size-4}
}
removechars
var2=$?
wat string
10
Dit kan ook de taak doen:
... | head -c -1
-c, --bytes=[-]NUM
print the first NUM bytes of each file; with the leading '-', print all but the last NUM bytes of each file