I am writing shell script for embedded Linux in a small industrial box. I have a variable containing the text pid: 1234
and I want to strip first X characters from the line, so only 1234 stays. I have more variables I need to "clean", so I need to cut away X first characters and ${string:5}
doesn't work for some reason in my system.
The only thing the box seems to have is sed
.
I am trying to make the following to work:
result=$(echo "$pid" | sed 's/^.\{4\}//g')
Any ideas?
${string:5}
doesn't work then you're not using Bash or another shell that supports that syntax. What shell and version are you using? What does your shebang look like? My guess is that you're using sh
(such as dash
) or possibly zsh
.
The following should work:
var="pid: 1234"
var=${var:5}
Are you sure bash
is the shell executing your script?
Even the POSIX-compliant
var=${var#?????}
would be preferable to using an external process, although this requires you to hard-code the 5 in the form of a fixed-length pattern.
Here's a concise method to cut the first X characters using cut(1)
. This example removes the first 4 characters by cutting a substring starting with 5th character.
echo "$pid" | cut -c 5-
git log --pretty=oneline | cut -c 42- | head
cut -c ${LEN}-
. The curly braces are used to concatenate the string with valid variable characters, in order to distinguish what is the variable and what isn't. If you want more information on this, then look up "bash variable string concatenation" for more resources on why / how this works.
Use the -r
option ("use extended regular expressions in the script") to sed
in order to use the {n}
syntax:
$ echo 'pid: 1234'| sed -r 's/^.{5}//'
1234
sed -r 's/.{5}$//'
to strip the last 5 characters instead
-r
(-E
in OS X, IIRC) if you escape the braces (don't know if that works in OS X, though).
-r
/ -E
) works in OS X.
Cut first two characters from string:
$ string="1234567890"; echo "${string:2}"
34567890
pipe it through awk '{print substr($0,42)}'
where 42 is one more than the number of characters to drop. For example:
$ echo abcde| awk '{print substr($0,2)}'
bcde
$
Chances are, you'll have cut
as well. If so:
[me@home]$ echo "pid: 1234" | cut -d" " -f2
1234
cut
is that it doesn't handle sequences of whitespace sensibly, using tr -s ' '
to "squeeze" spaces makes it behave better.
Well, there have been solutions here with sed
, awk
, cut
and using bash
syntax. I just want to throw in another POSIX conform variant:
$ echo "pid: 1234" | tail -c +6
1234
-c
tells tail at which byte offset to start, counting from the end of the input data, yet if the the number starts with a +
sign, it is from the beginning of the input data to the end.
Another way, using cut
instead of sed
.
result=`echo $pid | cut -c 5-`
I found the answer in pure sed supplied by this question (admittedly, posted after this question was posted). This does exactly what you asked, solely in sed:
result=\`echo "$pid" | sed '/./ { s/pid:\ //g; }'\``
The dot in sed '/./
) is whatever you want to match. Your question is exactly what I was attempting to, except in my case I wanted to match a specific line in a file and then uncomment it. In my case it was:
# Uncomment a line (edit the file in-place):
sed -i '/#\ COMMENTED_LINE_TO_MATCH/ { s/#\ //g; }' /path/to/target/file
The -i
after sed
is to edit the file in place (remove this switch if you want to test your matching expression prior to editing the file).
(I posted this because I wanted to do this entirely with sed as this question asked and none of the previous answered solved that problem.)
Rather than removing n characters from the start, perhaps you could just extract the digits directly. Like so...
$ echo "pid: 1234" | grep -Po "\d+"
This may be a more robust solution, and seems more intuitive.
This will do the job too:
echo "$pid"|awk '{print $2}'
awk -F": " '{print $2}'
. Still, not my favourite solution.
Success story sharing
${var:5:2}
will start at1
and return12
.