Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How cut characters from string and put it at the end- In shell

Tags:

linux

shell

sed

I want to be able to do the following:

String1= "HELLO 3002_3322 3.2.1.log"

And get output like:

output = "3002_3322 3.2.1.log HELLO"

I know the command sed is able to do this but I need some guidance.

Thanks!

like image 495
liangusburger Avatar asked Jan 17 '26 06:01

liangusburger


2 Answers

AWK

awk is one tool to do something like that:

echo "HELLO 3002_3322 3.2.1.log" | awk '{print $2$3" "$1}'

What it does:

  • awk, without delimiter flag of -F splits by whitespace sequences
  • that means, HELLO 3002_3322 and 3.2.1.log will be seen
  • HELLO is referred to by $1; 3002_3322 is $2 and so on
  • we print $2, then $3 then one space, then $1

SED

I have a unpretty looking sed example for you:

echo "HELLO 3002_3322 3.2.1.log" | sed 's_\(.*\)\s\(.*\)\s\(.*\)_\3 \2 \1_'

What it does:

  • nomenclature is s_<pattern>_<replacement>_
  • first s stands for substitute
  • _ is the delimiter
  • (.*) is paranthesis dot star parenthesis. That is the first group of characters we are asking sed to match. .* means match any sequence of characters or no characters at all. Ignore the \ before ( and ) for now
  • Notice the \s after the group. \s matches one space. So, we are asking sed to separate out (.*)\s - i.e. ()
  • We repeat that to tell sed - (group1)(group2)(group3)
  • First group's shorthand is \1, group2's shorthand is \2 etc.
  • For replacement, we tell sed to arrange \3 (group3) first, then \2 (group2) and then \1 (group1)

( is a special character in sed. So we have to escape it by a forward slash. So, (.*)\s(.*)\s(.*) becomes \(.*\)\s\(.*\)\s\(.*\). Oh so pretty!

like image 77
zedfoxus Avatar answered Jan 19 '26 19:01

zedfoxus


In sed you can do:

sed 's/\([^[:blank:]]*\)[[:blank:]]*\(.*\)/\2 \1/'

Which outputs 3002_3322 3.2.1.log HELLO.

Explanation

  1. The first word is captured by \([^[:blank:]]*\) The \(\) means I want to capture this group to use later. [:blank:] is a POSIX character class for whitespace characters. You can see the other POSIX character classes here:

http://www.regular-expressions.info/posixbrackets.html

The outer [] means match anyone of the characters, and the ^ means any character except those listed in the character class. Finally the * means any number of occurrences (including 0) of the previous character. So in total [^[:blank:]]* this means match a group of characters that are not whitespace, or the first word. We have to do this somewhat complicated regex because POSIX sed only supports BRE (basic regex) which is greedy matching, and to find the first word we want non-greedy matching.

  1. [[:blank:]]*, as explained above, this means match a group of consecutive whitespaces.

  2. \(.*\) This means capture the rest of the line. The . means any single character, so combined with the * it means match the rest of the characters.

  3. For the replacement, the \2 \1 means replace the pattern we matched with the 2nd capture group, a space, then the first capture group.

like image 42
bkmoney Avatar answered Jan 19 '26 18:01

bkmoney



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!