Hoe kan ik meer dan één substring tegelijk vervangen in bash?

Ik heb een map met afbeeldingsbestanden die in bash moeten worden herhaald. Terwijl ik echo, wil ik zowel de bestandsnaam als de extensie vervangen in een opdracht met één regel.

Voorbeeldbestanden:

images/file_name_1.jpg images/file_name_2.jpg 

Normaal gesproken kan ik een enkele vervanging als volgt doen:

 for i in images/*; do echo ${i/file/image}; done  

En de output wordt als:

 images/image_name_1.jpg images/image_name_2.jpg  

Hoe kan ik het in de lus houden en de “jpg” string ook vervangen door “png”? Het is maar een voorbeeld, ik zou de punt kunnen vervangen door komma enz.

Wanneer ik dit probeer:

 for i in images/*; do echo ${{i/jpg/png}/file/image}; done  

Het werkt niet. Ik zou “geen andere oplossing of idee kunnen vinden. Is dit mogelijk – zo ja, hoe?

Reacties

  • Ik don ' weet niet waarom dit niet ' werkte in bash, maar geneste vervangingen werken precies zoals je verwachtte in zsh. Afhankelijk van je omgeving zou je kunnen overwegen om een better shell;)

Answer

De eenvoudige benadering zou zijn om het resultaat toe te wijzen aan een variabele, en vervolgens te werken met die variabele. Voorbeeld:

 for filename in images/* do echo "filename is now $filename" filename=${filename/jpg/png}; echo "filename is now $filename" filename=${filename/file/image}; echo "filename is now $filename" echo "final filename is ${filename}" done  

Reacties

  • Dit antwoord is niet compleet. de vervangingen zullen overal in de bestandsnaamstrings van toepassing zijn. Op basis van de vraag wil Kubilay een voorvoegsel en een extensie (achtervoegsel) vervangen. kun je dit wijzigen en hiermee rekening houden : $ {var / # Pattern / Replacement} Als het voorvoegsel van var overeenkomt met Pattern, vervang dan Pattern door Vervanging. $ {var /% Pattern / Replacement} Als achtervoegsel van var komt overeen met Pattern, en vervang dan Pattern door Vervanging.
  • @rMistero Daar ' s is er geen regel tegen het plaatsen van een ander antwoord alleen omdat een antwoord is geaccepteerd. In feite denk ik dat u dat zou moeten doen, vooral omdat de semantiek van wat u voorstelt, anders is. Dat gezegd hebbende, dit is de manier om te doen wat het OP zei te hebben geprobeerd, dus zelfs als er andere resultaten zijn die ook geldig zouden kunnen zijn, denk ik dat het veilig is om aan te nemen dat dit in overeenstemming is met wat het OP wilde bereiken. / li>

Answer

U kunt de vorige vervanging aan een variabele toewijzen en in plaats daarvan replace op die variabele uitvoeren

 for i in images/* do j=${i/jpg/png} echo ${j/file/image} done  

Reacties

  • Niet zeker als het werkt. " voor i in afbeeldingen / *; do j = {i / jpg / png} echo $ {j / file / image}; gedaan " echos " {i / jpg / png} " herhaaldelijk.
  • Nu ja: " voor i in afbeeldingen / *. jpg; do j = $ {i / jpg / png}; echo $ {j / file / image}; gedaan ". Bedankt!

Antwoord

om een willekeurige string te wijzigen:

$ echo "images/file_name_1.jpg" | perl -pE "s/file/image/;s/jpg$/png/;" images/image_name_1.png 

een snelkoppeling om te hernoemen (wat misschien het uiteindelijke doel is:

$ rename "s/file/image/;s/jpg$/png/;" "$i" 

Reacties

  • Ik denk nog steeds dat het een keer aanroepen van Perl voor elk bestand overdreven is, maar dit geeft nu tenminste een antwoord op de vraag. 🙂
  • @MichaelKj ö rling U hoeft niet ' Perl voor elk bestand op te roepen, u kunt rename … images/* doen. Maar dit vereist een op Debian gebaseerde distributie (rename op andere Linux-varianten is een heel ander commando).
  • @Gilles Ik dacht meer aan de eerste versie, vooral omdat er ' niets in de vraag staat zoals gesteld over het hernoemen van bestanden. De originele (bewerkte respijtperiode) versie van dit antwoord had alleen de opdrachtsuggestie rename.

Geef een reactie

Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *