How to edit curl output in place? - linux

I am curling commands for a bash script to run an installation on my linux system and then piping it to the bash console.
curl -G website/bashscript.sh | sudo bash
However the commands I receive from curl has an added
echo "Rebooting"
reboot
at the end.
This curl and sudo command is within my own bash script I am writing for automating an installation process.
How do I remove the echo and reboot command from this text and pipe it to bash? I would rather not save it to a file, edit it, then pass it to bash since I really don't want to remove the text file afterwards.
Thanks!

Remove the last line, if it is the word reboot:
sed '${/^reboot$/d}'
The sed syntax: $ selects the last line. { starts a block. /^reboot$/ selects lines, which contain only the word reboot (^ matches the beginning and $ matches the end of the line). d deletes the line in case of a match. } closes the block.
Remove the last line, if it is the phrase echo "Rebooting":
sed '${/^echo "Rebooting"$/d}'
All together:
curl -G website/bashscript.sh |
sed '${/^reboot$/d}' |
sed '${/^echo "Rebooting"$/d}' |
sudo bash

Another variant with grep, which removes the unwanted commands in any line:
curl … | grep -vx 'echo "Rebooting"
reboot' | …

Related

Trimming string up to certain characters in Bash

I'm trying to make a bash script that will tell me the latest stable version of the Linux kernel.
The problem is that, while I can remove everything after certain characters, I don't seem to be able to delete everything prior to certain characters.
#!/bin/bash
wget=$(wget --output-document - --quiet www.kernel.org | \grep -A 1 "latest_link")
wget=${wget##.tar.xz\">}
wget=${wget%</a>}
echo "${wget}"
Somehow the output "ignores" the wget=${wget##.tar.xz\">} line.
You're trying remove the longest match of the pattern .tar.xz\"> from the beginning of the string, but your string doesn't start with .tar.xz, so there is no match.
You have to use
wget=${wget##*.tar.xz\">}
Then, because you're in a script and not an interactive shell, there shouldn't be any need to escape \grep (presumably to prevent usage of an alias), as aliases are disabled in non-interactive shells.
And, as pointed out, naming a variable the same as an existing command (often found: test) is bound to lead to confusion.
If you want to use command line tools designed to deal with HTML, you could have a look at the W3C HTML-XML-utils (Ubuntu: apt install html-xml-utils). Using them, you could get the info you want as follows:
$ curl -sL www.kernel.org | hxselect 'td#latest_link' | hxextract a -
4.10.8
Or, in detail:
curl -sL www.kernel.org | # Fetch page
hxselect 'td#latest_link' | # Select td element with ID "latest_link"
hxextract a - # Extract link text ("-" for standard input)
Whenever I need to extract a substring in bash I always see if I can brute force it in a couple of cut(1) commands. In your case, the following appears to work:
wget=$(wget --output-document - --quiet www.kernel.org | \grep -A 1 "latest_link")
echo $wget | cut -d'>' -f3 | cut -d'<' -f1
I'm certain there's a more elegant way, but this has simple syntax that I never forget. Note that it will break if 'wget' gets extra ">" or "<" characters in the future.
It is not recommended to use shell tools grep, awk, sed etc to parse HTML files.
However if you want a quick one liner then this awk should do the job:
get --output-document - --quiet www.kernel.org |
awk '/"latest_link"/ { getline; n=split($0, a, /[<>]/); print a[n-2] }'
4.10.8
sed method:
wget --output-document - --quiet www.kernel.org | \
sed -n '/latest_link/{n;s/^.*">//;s/<.*//p}'
Output:
4.10.8

Linux shell script - String trimming for dash

I am attempting to get the mac address from my Raspberry Pi take the last 6 characters of the mac to use as the hostname alongside a fixed string.
here is what I'v managed to get working from other sources so far, but I am now totally stuck trying to trim the string down.
#!/bin/sh -e
MAC="$( sed "s/^.*macaddr=\([0-9A-F:]*\) .*$/\1/;s/://g" /proc/cmdline )"
MAC1="${MAC??????%}"
echo "$MAC1"
the shell being used by the Pi appears to be Dash, so the usual BASH commands that would have this done in no-time don't want to work or seem to generate errors when run within the script.
The full script that I am using in rc.local is below.
any advice on a way to-do this would be greatly received.
MAC="pi""$( sed "s/^.*macaddr=\([0-9A-F:]*\) .*$/\1/;s/://g" /proc/cmdline )"
echo "$MAC" > "/etc/hostname"
CURRENT_HOSTNAME=$(cat /proc/sys/kernel/hostname)
sed -i "s/127.0.1.1.*$CURRENT_HOSTNAME/127.0.1.1\t$MAC/g" /etc/hosts
hostname $MAC
If you have the cut command on your Pi, you could
do
MAC1=$( echo $MAC | cut -c 7-12 )
Since you're already using sed to process the string, I'd suggest adding another command:
MAC=$(sed -e 's/^.*macaddr=\([0-9A-F:]*\) .*$/\1/' \
-e 's/://g' \
-e 's/.*\(.\{6\}\)/\1/' /proc/cmdline)
The extra sed command extracts the last 6 characters from each line (I assume that you only have one?). You can combine the commands into a single string if you prefer, though I find this approach to be more readable.

Terminal seems to be appears to be cutting off a bash command midway

I'm running a bash script on OSX Yosemite and Mavericks.
When I run the script the last line seems to be getting cut off part way. The last command loads a daemon - this is how it appears in the script:
sudo -u <USERNAME> launchctl load -w -F /Library/LaunchAgents/ExecuteScriptProcess.plist
It seems that once out of 10 or so times that I run this script the last command will not work. This is the output I'm receiving in the terminal:
: No such file or directoryocess.plist
Note how part of the filename ocess.plist was essentially concatenated to the end of the output and the name of the command does not appear before the colon.
This behaviour seems to show up randomly. Has anyone come across this before?
This is due to carriage returns in your script or data. The bash tag wiki has more information:
Check whether your script or data has DOS style end-of-line characters
Use cat -v yourfile or echo "$yourvariable" | cat -v .
DOS carriage returns will show up as ^M after each line.
If you find them, delete them using dos2unix (a.k.a. fromdos) or tr -d '\r'

Paste a chunk of text from stdin to a specific location in a file

I'm trying to figure out how to efficiently copy-paste from X application to the terminal. Specifically I want to highlight a text section in my web browser, then paste this commented to a file after the shebang line.
the code I have so far is this:
xclip -o | sed 's/^/#/' | sed '2n' myscript.pl
the first command takes the text that I have highlighted in my browser
the second command comments the lines by adding #
the last bit does not work..
what I am trying to do here is append the text after line number 2 to my script. But obviously I am doing this wrong.. Does anyone have a helpful suggestion?
You can use sed read for safely handling all types of input, including input with special characters and multiple lines. This requires an intermediate file:
xclip -o | sed -e 's/^/#/g' -e '$s/$/\n/' > TMP && sed -i '1r TMP' den && rm TMP
sed only operates on one input stream (either a pipe or a file), if you are using the output of xclip as the data stream then you can't also tell sed to read from a file. Instead you could use command substitution to store the modified output, and use that in a separate command. How about:
sed "2i$(xclip -o | sed 's/^/#/')" myscript.pl
This will print the amended file to stdout, if you want to edit the file itself then use the -i flag.

use of sed substitute in shell script doesn't work

I have made an install script which basically inserts some RewriteRule right after RewriteEngine On line by using sed inside a shell script
#!/bin/bash
REWRITE_RULE="RewriteRule \^catalog\/category\/view\/id\/([0-9]+)$ http:\/\/localhost\/app\/#?c=$1 [NE,L,R=301]"
FILE_PATH=".htaccess"
sed -i "s/RewriteEngine on/RewriteEngine on\n\n$REWRITE_RULE/g" $FILE_PATH
it does nothing but gives some error like
: No such file or directory
I tried same commands in shell and it worked without any issues and updated my .htaccess file
I am new to shell scripting so don't know the difference of using same command through shell and through script.. please guide
The script itself is fine. Are you sure that the lines posted above are exactly as you took them from your script?
The error message indicates that you provided an empty name as the filename, thus I suggest you put a
echo "FILE_PATH: $FILE_PATH"
directly before your sed command in order to check whether the variable is set correctly.
You'll find that your script contains carriage returns due to being saved with DOS end-of-line characters. Use tr -d '\r' <brokenscript >fixedscript to fix your script.
Here's a copy of a session with the problem reproduced and fixed:
$ cat file
var=foo
$ cat myscript
sed -i s/foo/bar/ file
$ bash myscript
: No such file or directory
$ shellcheck myscript
In myscript line 1:
sed -i s/foo/bar/ file
^-- SC1017: Literal carriage return. Run script through tr -d '\r' .
$ tr -d '\r' < myscript > fixedscript
$ bash fixedscript
$ cat file
var=bar
$

Resources