Terminal command line quick navigation - linux

I would like to move between the command line arguments in a fast way. For example, if I have the following command line:
> do_something_with /very_long_path/to_a_very_long_directory/ more_args
^ ^
I would like to skip the whole path (jump between the ^ symbols). I'm already familiar with word mode (Alt+B and Alt+F) but in some scenarios it's not enough to navigate quickly between the arguments.

In bash, you can set the cursor to the previous given character using the following features:
character-search and character-search-backward features.
ctrl+], (resp. alt+ctrl+]) + searched_character
In your example, you can search backward for a space.
> do_something_with /very/long/path/\ with_spaces\ directory/ more_args
^ ^
Unfortunately, this will not work so well with paths like:
> do_something_with /very_\ long_path/to_a_\ very_long_directory/ more_args
As a sidenote, you can use ctrl+a and ctrl+e to go at the beginning / end of a line.

There are (quote from manual)
shell-forward-word ()
Move forward to the end of the next word. Words are delimited by non-quoted shell metacharacters.
and
shell-backward-word ()
Move back to the start of the current or previous word. Words are delimited by non-quoted shell metacharacters.
I have bound them to Ctrl+Alt+F and Ctrl+Alt+B by adding this to my .inputrc:
"\e\C-f": shell-forward-word
"\e\C-b": shell-backward-word

For vi/vim users ctrl+] + char can be used to quickly navigate to the first occurance of a given char. Which is equivalent to f + char in vi/vim.

Related

how to visualise and delete trailing newline at the end of file in vim\nvim

Sometimes I need to edit files which should not end with a newline.
However vim\nvim by default do not visualise in any way the newline character at the end of file. Therefore I am not able to:
visually confirm if the file has a newline character at the end or not
remove that character
Are there any setting which would allow me to see the tailing newline character and edit it in the same way as any other characters?
For example, after create 2 files as follows:
echo test > file-with-newline
echo -n test > file-without-newline
opening first one with nvim file-with-newline shows:
test
~
~
file-with-newline
opening second one with nvim file-without-newline shows:
test
~
~
file-without-newline
Navigating with the cursor to the end of line in either case yields the same result (the cursor stops after last visible character: t). There is no way to tell if the newline is there or not, let alone remove it using familiar commands used to remove ordinary characters (or newlines within the file).
You can enable the option :help 'list':
:set list
to show that "newline character" as a $ at the end of the line (among other things):
Note, however, that the option doesn't make the character "editable" in any way.
if the file has a newline character at the end or not
:set eol?
endofline
remove that character
:set noeol nofixeol
:update

vim command to add a semi colon at the end of all lines in a file beginning with a pattern

I would like to insert a semi-colon at the end of all the lines beginning with some pattern(MATCH_) in a file.
Whats the command to use.
This can be done with the :g command:
:g/^<pattern>/normal A;
A bit of an explanation:
This finds all lines starting with (due to the ^) the specified <pattern> and then executes the command normal A; which switches to normal mode, then does A to append to the line, followed by typing ;.

Understanding how a Sed script breaks down into individual commands

I'm new to sed, can you tell me what the following does? I can't find a complete regex in the command from below.
sed -e ':a;N;$!ba;s/>[[:space:]]*\n/>\\\n/g' nlTest1.txt > nlTest2.txt
Are we having 3 commands together?
:a;N;$!ba;s
>[[:space:]]*\n
>\\\n/g
Or I'm not intrepreting the command correctly.
The partitioning of the commands is:
:a;N;$!ba, which is a common idiom for reading the entire input file into the pattern space (buffer to operate on) at once, in a loop; it is composed of 3 ;-separated commands:
label :a (defines a script location that can be jumped to)
function N (reads the next line and appends it to the pattern space)
$! ba, which branches (b) to label a, if the input line is not (!) the last ($) one.
s/>[[:space:]]*\n/>\\\n/g is a regular s function call in the form s/<regex>/<substitution-string>/; here, all occurrences of a > followed by any run of whitespace followed by a newline are replaced with just >\ and a newline.

Re run previous command with different arguments

If you want to re run a command with the same arguments you can do something like this:
vim long_filename
cat !$ #same as 'cat long_filename'
This saves having to type out the previous argument again when it is passed to cat.
However, how would I pass arguments that are not the same to the last run script/command?
long_annoying_script_name arg1 arg2
? arg3 arg4 #? signifies shortcut symbols such as '!$'
Of course I could just press the 'up' arrow and delete the arguments and type the new ones, but is there a shorter/faster way?
I DO NOT want to assign an alias.
!:0 should do the trick. From the zsh documentation:
Word Designators
A word designator indicates which word or words of a given command line
are to be included in a history reference. A `:' usually separates the
event specification from the word designator. It may be omitted only
if the word designator begins with a `^', `$', `*', `-' or `%'. Word
designators include:
0 The first input word (command).
n The nth argument.
^ The first argument. That is, 1.
$ The last argument.
% The word matched by (the most recent) ?str search.
x-y A range of words; x defaults to 0.
* All the arguments, or a null value if there are none.
x* Abbreviates `x-$'.
x- Like `x*' but omitting word $.
(It works with bash, too.) There’s also !-1 if you find that more convenient to type.
#TL;DR
Alt+0+.: inserts last command without the arguments
Tested on Ubuntu 18.04 with the default keybinding settings (i.e Emacs keybindings)
You can combine keyboard shortcuts
Let's consider the last command to be:
mv foo bar
up , Ctrl+w: last command without the last word = mv foo
Alt+0+.: first argument of last command = mv
Some useful shortcuts:
Alt+.: insert last argument from last command (repeat to go back in history)
Alt+number+.: insert #nth last argument from last command (repeat to go back in history)
Alt+- , number , Alt+., zsh: Alt+-+#+.: insert #nth first argument from last command (repeat to go back in history)
Cut commands (relative to cursor's position)
Ctrl+w: cuts last word
Alt+d: cuts next word
Ctrl+k: cuts everything after
Ctrl+u, zsh: Alt+w: cuts everything before
zsh: Ctrl+u: cuts the entire command (In bash you can combine Ctrl+u , Ctrl+k)
Ctrl+y: paste characters previously cut with any Cut command. In bash You can chain cut commands, and Ctrl+y will paste them all.
Ctrl+_: undo last edit (very useful when exceeding Ctrl+w)
Ctrl+left: move to last word
Ctrl+right: move to next word
home or Ctrl+a: move to start of command
end or Ctrl+e: move to end of command
To see all shortcuts available
bash: bind -lp
zsh: bindkey -L
Unfortunately there are some limitations
"words" only includes a-zA-Z characters, so any symbol character will stop word-shortcuts.
So if last argument was a url and you want to erase it with Ctrl+w it will be a pain.
E.g: curl -I --header "Connection: Keep-Alive" https://stackoverflow.com/questions/38176514/re-run-previous-command-with-different-arguments
To erase that url using Ctrl+w, you'd have to repeat it 12 times.
It would be great to have similar shortcuts that only stops at the space character
I'm keeping this up-to-date here: https://github.com/madacol/docs/blob/master/bash-zsh_TerminalShorcuts.md

What is the shorthand for the first argument of the previous comment in bash? last is '$!'

What is the special character which indicate first ?
if we do
$ vi .bashrc
$ source !$
this !$ will replaced by .bashrc
because ! means previous line(am I correct?), $ means last word (for sure)
then what is first?
I want to insert some string in every line in vi editor using
:%s/find-key-word/replaced-keyword/g
in here, if I put
:%s/$/example/g
in vi editor, it will append in all lines with example.
I want to insert all in front of all string every line.
I know I can use visual block (ctrl+v) and select all front lines and insert (shift+i) insert some word and escape(esc) will do the same... but I want to do in one shot..
please let me know how to do..
Thanks in advance
There are two questions, so you are getting two kinds of answers :)
The bash command history has only a passing similarity to the vi regular expression syntax.
^ is the beginning of line in vi. $ is the end of line in vi.
!!:0 is one way of accessing the first word of the previous command in bash
!$ is one way of accessing the last word of the previous command in bash
To indicate beginning of line, the symbol used is:
^
See an example:
$ cat a
hello!
this is me
testing some
stuff
$ sed 's/^/XXX/' a
XXXhello!
XXXthis is me
XXXtesting some
XXXstuff
The character you are looking for is ^.
For example, :%s/^/example/g will prepend all lines with the string example.
In bash, !^ refers to the first argument of the previous command, and !$ the last argument.

Resources