I have done a program that receives input from the terminal with the readline function in c (https://eli.thegreenplace.net/2016/basics-of-using-the-readline-library/), readline saves keyboard input from the terminal (basically a read for the stdin) and saves it inside a buffer.
Imagine, when my program is executed, it just prints a message on the screen like: *Enter a command: * and I can write a bash command and it's going to execute it (Just like bash).
I wanted to do a test (In python, c++ or bash) that is going to start the program, and writes into the readline and check is output compared to bash, does anyone knows a way to do it?
Here is an initial bash script that randomizes input with some properties:
for i in {1..5}; do
input=$(echo {A..Z} {a..z} | tr ' ' "\n" | shuf | xargs | tr -d ' ' | cut -b 1-18)
echo ${input}
/path/to/your_program < ${input}
done
You can add characters, make the input shorter etc.
I think what you want is to grab the input in python (I suggest you use the input() function), store it in a variable, then print it out in the terminal using print()
Related
I am trying to find a way to extract a value for a Monitoring Data file and use it further. Using an SSH connection (with password) i would like to access a file which is remotely located. The in this file I would like to search for a particular sensor name. Since this file contains data from lot of sensors and from different timesteps, I would like to pick the last (latest) string and next to this string is the sensor value and I would like to copy it and write it in a local data file and use it further in the programming. I could copy the whole file from server to local but the whole file is big and the file keeps changing every hour.
Time Sensor-name Sensor-value
25-05-2018;15:24 t_amb 24.8
25-05-2018;15:24 t_room 21.2
25-05-2018;15:24 G_global 120
25-05-2018;15:25 t_amb 25
25-05-2018;15:25 t_room 21
25-05-2018;15:25 G_global 227.8
For Example in the above mentioned file which is located in an another computer which is connected via SSH port, I would just like to search for the string 't_room' and find the last occurrence of it in the remote file and write the value next to it '21' into a file which is located at a directory locally.
Edit: More or less I want to do a similar thing but instead of a bash script I want to do it in Python :
sshpass -piHEM_MT17 ssh 192.168.101.53 "keysight" | egrep "SP_t_5_roh" | cut -d" " -f4 | tail -n 1 > /run/user/1000/temperaturtest.txt
You can pipe the data to grep to select the last line with tail containing "t_room", then print the 3rd column separated by space using awk.
For example, if your data is saved in log.txt:
cat log.txt | grep t_room | tail -n 1 | awk -F" " '{print $3}'
You may need to make some small changes, but this could easily work verbatim.
import pexpect
import re
def fetch_sensor_last(sensor_name):
c = pexpect.spawn('ssh user#hostaddress')
c.expect(': ') # wait for password prompt
c.sendline('yourpassword')
c.expect('$ ') # wait for unix prompt
c.sendline('cat /full/path/to/log.txt | grep %s | tail -n 1')
c.expect('$ ')
c.close() # close ssh child process
tail_output = c.before.splitlines()[0] # get command output
# regex matches date, time, and sensor value (see www.regex101.com)
match = re.match(
rb'(\d+\-\d+\-\d+);(\d+:\d+)\s+\w+\s+([\d\.]+)', tail_output)
if match:
return match.groups()
date, time, value = fetch_sensor_last(sensor_name)
Pexpect essentially runs the command you spawn it with in bash, then you simply .expect('pattern') to wait for expected (obviously, the namesake) prompts or other text patterns. If you need to retrieve text, the normal way is to first expect the next prompt, then access the bytes object stored in .before to get all the ascii bytes since the last .expect() command.
If you need to troubleshoot the automation, I would suggest running the command manually outside of python, then stepping through the process and recording all the prompts you need to deal with (including prompts for rsa warnings and the like), and ensuring you are not missing anything.
Please note that the strings you get from pexpect are all bytes objects, and you can convert them to normal python strings via bytesobj.decode().
I am using Vim (8.0) and tmux (2.3) together in the following way: In a tmux session I have a window split to 2 panes, one pane has some text file open in Vim, the other pane has some program to which I want to send lines of text. A typical use case is sending lines from a Python script to IPython session running in the other pane.
I am doing this by a Vim script which uses python, code snippet example (assuming the target tmux pane is 0):
py import vim
python << endpython
cmd = "print 1+2"
vim_cmd = "silent !tmux send-keys -t 0 -l \"" + cmd + "\"" # -l for literal
vim.command(vim_cmd)
endpython
This works well, except for when cmd has some characters which has to be escaped, like %, #, $, etc. The cmd variable is read from the current line in the text file opened in Vim, so I can do something like cmd = cmd.replace('%', '\%') etc., but this has 2 disadvantages: first, I don't know all the vim characters which have to be escaped, so it has been trial and error up until now, and second, the characters " is not escaped properly - that is in the string Vim gets, the " just disappears, even if I do cmd = cmd.replace('"', '\"').
So, is there a general way to tell Vim to not interpret anything, just get a raw string and send it as is? If not, why is the " not escaped properly?
Vimscript
You're looking for the shellescape() function. If you use the :! Vim command, the {special} argument needs to be 1.
silent execute '!tmux send-keys -t 0 -l ' . shellescape(cmd, 1)
But as you're not interested in (displaying) the shell output, and do not need to interact with the launched script, I would switch from :! to the lower-level system() command.
call system('tmux send-keys -t 0 -l ' . shellescape(cmd))
Python
The use of Python (instead of pure Vimscript) doesn't have any benefits (at least in the small snippet in your question). Instead, if you embed the Python cmd variable in a Vimscript expression, now you also need a Python function to escape the value as a Vimscript string (something like '%s'" % str(cmd).replace("'", "''"))). Alternatively, you could maintain the value in a Vim variable, and access it from Python via vim.vars.
I am using a bash script to call google-api's upload_video.py (https://developers.google.com/youtube/v3/guides/uploading_a_video )
I have a mp4 called output.mp4 which I would like to upload.
The problem is I cannot get my array to work how I would like.
This new line character is "required" because my arguments to python script contain spaces.
Here is a simplified version of my bash script:
# Operator may change these
hold=100
location="Foo, Montana "
declare -a file_array=("unique_ID_0" "unique_ID_1")
upload_file=upload_file.txt
upload_movie=output.mp4
# Hit enter at end b/c \n not recognized
upload_title=$location' - '${file_array[0]}' - Hold '$hold' Sweeps
'
upload_description='The spectrum recording was made in at '$location'.
'
# Overwrite with 1st call > else apppend >>
echo "$upload_title" > $upload_file
echo "$upload_description" >> $upload_file
# Load each line of text file into array
IFS=$'\n'
cmd_google=$(<$upload_file)
unset IFS
nn=1
for i in "${cmd_google[#]}"
do
echo "$i"
# Delete last character: \n
#i=${i[-nn]%?}
#i=${i: : -nn}
#i=${i::${#i}-nn}
i=${i%?}
#i=${i#"\n"}
#i=${i%"\n"}
echo "$i"
done
python upload_video.py --file=$upload_movie --title="${cmd_google[0]}" --description="${cmd_google[1]}"
At first I attempted to remove the new line character, but it appears that the enter or \n is not working how I would like, each line is not separate. It writes the title and description as one line.
How do I modify my bash script to recognize a newline character?
This is much simpler than you are making it.
# Operator may change these
hold=100
location="Foo, Montana"
declare -a file_array=("unique_ID_0" "unique_ID_1")
upload_file=upload_file.txt
upload_movie=output.mp4
upload_title="$location - ${file_array[0]} - Hold $hold Sweeps"
upload_description="The spectrum recording was made in at $location."
cat <<EOF > "$upload_file"
$upload_title
$upload_description
EOF
# ...
readarray -t cmd_google < "$upload_file"
python upload_video.py --file="$upload_movie" --title="${cmd_google[0]}" --description="${cmd_google[1]}"
I suspect the readarray command is all you are really looking for, since much of the above code is simply creating a file that I assume you are receiving already created.
I figured it out with help from chepner's answer. My question hid the fact that I wanted to write new line characters into the video's description.
Instead of adding a new line character in the bash script, it is much easier to have a text file which contains the correctly formatted script and read it in, then concatenate it with run-time specific variable.
In my case the correctly formatted text is called description.txt:
Here is a snip of my description.txt which contains newline characters
Here is my final version of the script:
# Operator may change these
hold=100
location="Foo, Montana"
declare -a file_array=("unique_ID_0" "unique_ID_1")
upload_title="$location - ${file_array[0]} - Hold $hold Sweeps"
upload_description="The spectrum recording was made in at $location. "
# Read in script which contains newline
temp=$(<description.txt)
# Concatenate them
upload_description="$upload_description$temp"
upload_movie=output.mp4
python upload_video.py --file="$upload_movie" --title="$upload_title" --description="$upload_description"
I'm running grep from within a python script like so:
last_run_start = os.system("cat %(file)s | grep '[0-24]:[0-59]' | tail -n1" % locals())
Which pulls out the last timestamp in file. When I do this through the Python command line, or use that grep command through regular terminal, I get what would be expected - the last line containing a timestamp.
However, when run from this script last_run_start is returning this:
18:23:45
0
Whats causing this '0' to appear, let alone on a new line? More importantly, how can I remove it from last_run_start?
os.system returns the exit code of the command you've run, which in this case seems to be 0.
The output of the command goes directly to stdout and isn't stored in last_run_start, if you want that you should use Popen or check_output from the subprocess module.
I guess the 0 ends up being printed because you're printing last_run_start somwhere.
I am trying to write a code in python that will take some information from top and put it into a file.
I want to just write the name of the application and generate the file. The problem i am having is that i can't get the output of the pidof command so i can use it in python. My code looks like this :
import os
a = input('Name of the application')
val=os.system('pidof ' + str(a))
os.system('top -d 30 | grep' + str(val) + '> test.txt')
os.system('awk '{print $10, $11}' test.txt > test2.txt')
The problem is that val always has 0 but the command is returning the pid i want. Any input would be great.
First up, the use of input() is discouraged as it expects the user to type in valid Python expressions. Use raw_input() instead:
app = raw_input('Name of the application: ')
Next up, the return value from system('pidof') isn't the PID, it's the exit code from the pidof command, i.e. zero on success, non-zero on failure. You want to capture the output of pidof.
import subprocess
# Python 2.7 only
pid = int(subprocess.check_output(['pidof', app]))
# Python 2.4+
pid = int(subprocess.Popen(['pidof', app], stdout=subprocess.PIPE).communicate()[0])
# Older (deprecated)
pid = int(os.popen('pidof ' + app).read())
The next line is missing a space after the grep and would have resulted in a command like grep1234. Using the string formatting operator % will make this a little easier to spot:
os.system('top -d 30 | grep %d > test.txt' % (pid))
The third line is badly quoted and should have caused a syntax error. Watch out for the single quotes inside of single quotes.
os.system("awk '{print $10, $11}' test.txt > test2.txt")
Instead of os.system, I recommend you to use the subprocess module: http://docs.python.org/library/subprocess.html#module-subprocess
With that module, you can communicate (input and output) with a shell. The documentation explains the details of how to use it.
Hope this helps!