Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

replace strings in zsh command line

I use zsh and emacs keybindings. Some time I need to execute the same command with different input. The input ususally have common substrings. Is there an easy way to replace parts of previous command with some other string? For example, the previous command is:

cat chr2.unknow.feature.filtered ../chr2.unknow.feature.filtered ../train/chr2.unknow.withpvalue.feature.filtered > chr2.combined.txt

How could I easily replace 'chr2' with 'chr3'?

An extension to the question, how to replace several different substrings in the command to other different strings:

cat chr1.unknow.feature.filtered ../chr2.unknow.feature.filtered ../train/chr3.unknow.withpvalue.feature.filtered

How to replace, let's say, 'chr1' with 'chrX', 'chr2' wtih 'chrY', 'chr3' with 'chrZ'?

Thanks.

like image 862
Rainfield Avatar asked Apr 25 '13 18:04

Rainfield


People also ask

How do you replace a string in a file in shell script?

Use Stream EDitor (sed) as follows: sed -i 's/old-text/new-text/g' input.txt. The s is the substitute command of sed for find and replace. It tells sed to find all occurrences of 'old-text' and replace with 'new-text' in a file named input.txt.

How do I replace a string in a bash script?

The 'sed' command is used to replace any string in a file using a bash script. This command can be used in various ways to replace the content of a file in bash. The 'awk' command can also be used to replace the string in a file.

How do I replace a multiple word file in Linux?

s/search/replace/g — this is the substitution command. The s stands for substitute (i.e. replace), the g instructs the command to replace all occurrences.


2 Answers

You can also do fast history substitution with ^old^new (a lot faster than !!:s^old^new^)

~ % cd /tmp
/tmp % ^tmp^etc  # <-- changes tmp for etc
/tmp % cd /etc
/etc % 

This only changes the first occurrence. If you need more, use any of history modifiers. Example: global changes:

/etc % echo tmp tmp tmp
tmp tmp tmp
/etc % ^tmp^etc
/etc % echo etc tmp tmp  # <--- only the first tmp got changed
etc tmp tmp
/etc % ^tmp^etc^:G       # <-- 'global'

PS: search the zshexpn manual for ^foo^bar to find the section describing this. Scroll down a little (in the manual), and you'll see the 'history expansion modifiers' list.

PS: For multiple substitution, do: ^old1^new1^:s^old2^new2^ etc

like image 94
Francisco Avatar answered Sep 20 '22 21:09

Francisco


To acomplish what you asked for directly:

$ !!:s/chr1/chrX/:s/chr2/chrY/:s/chr3/chrZ/

this will modify the last command entered. To perform global substitution, use :gs/a/b/.

Example:

$ man zshall
$ !!:gs/man/less/:gs/zshall/.history/<TAB>
$ less .history

Read more in man zshexpn -- ZSH expansion and substitution.

like image 27
Tom Regner Avatar answered Sep 17 '22 21:09

Tom Regner