跳到主要内容

bash

Control operators & and &&

When resolving cherry-pick conflicts on multiple branches (PRs), I often use the following command:

gh pr checkout PR_NUMBER
# Resolve conflicts
# Commit and push
git commit -a -S -m "resolve conflicts" && git push &
# Repeat for other PRs
gh pr checkout PR_NUMBER

The & operator is used to run the command in the background. The && operator is used to run the git push command only if the git commit command succeeds.

quote

If a command is terminated by the control operator &, the shell executes the command in the background in a subshell. The shell does not wait for the command to finish, and the return status is 0.

An AND list has the form

command1 && command2

command2 is executed if, and only if, command1 returns an exit status of zero.

For more details, refer to Shell Grammar: Lists.

提示

You can also use the bg command to run a command in the background. For example:

  1. Run a time-consuming command in the foreground, such as git pull.
  2. Press Ctrl+Z in the terminal to stop the git pull command. (Ctrl+Z sends the SIGTSTP signal to the process.)
  3. Run the bg command to continue the git pull command in the background.

For more details, refer to Job Control Builtins.

Remove a substring from a string

You can get more solutions from Stackoverflow/16623835.

For more details about #, ##, %, and %%, refer to Shell Parameter Expansion.

Remove the prefix using #

In ${parameter#word}, # is used to remove the shortest matching pattern word from the beginning of parameter.

var="test-123"
echo "${var#test-}" # 123

When you use find ${DIR_PATH} command to search for files, the result will be prefixed with ${DIR_PATH}. To remove the prefix, you can use the # operator. For example:

find ${DIR_PATH} | while IFS= read -r DIR; do
echo "${DIR#${DIR_PATH}}"
done

You can also use the sed command to perform the same operation. For more details, refer to sed.

find ${DIR_PATH} | while IFS= read -r DIR; do
echo "${DIR}" | sed "s~^${DIR_PATH}~~"
done

The following example shows the result before and after removing the prefix:

find . -maxdepth 3 -mindepth 3 | while IFS= read -r DIR; do
echo "${DIR}"
done
# ./website/docs
# ./website/blog
# ./website/yarn.lock
# ./website/package.json
# ./website/static
# ./website/docsearch.json
提示

What is the difference between # and ##?

  • # removes the shortest matching pattern word from the beginning of parameter.
  • ## removes the longest matching pattern word from the beginning of parameter.
var="test-test-123"
echo "${var#test-}" # test-123
echo "${var#*test-}" # test-123
echo "${var##*test-}" # 123

In the following example, a*b pattern matches any sequence that starts with a and ends with b.

var="aaabbbccc"
echo "${var#*a}" # aabbbccc
echo "${var##*a}" # bbbccc
echo "${var#a*b}" # bbccc
echo "${var##a*b}" # ccc
echo "${var#a*c}" # cc
echo "${var##a*c}" #

Remove the suffix using %

In ${parameter%word}, % is used to remove the shortest matching pattern word word from the end of parameter.

var="test-123"
echo "${var%-123}" # test
提示

What is the difference between % and %%?

  • % removes the shortest matching pattern word from the end of parameter.
  • %% removes the longest matching pattern word from the end of parameter.