I really can not figure how to do this.
I am trying to create a snippet that will read a file (the name I will get it by selecting it so it will be in the ${VISUAL}) and then using grep extract a line from it.
What I tried is something like
!v cat ${VISUAL} | grep "some text"
but of course that in shell ${VISUAL} has a different value.
I tried something in python, but I am lost. All I could get was
!p snip.rv=snip.v.text
that will give me the value for ${VISUAL}
Thank you for your help.
Maybe for your specific case you could use the vim builtin :read function ?
It's not quite grep, but if you're okay with Python-style regex, you can do this:
`!p
import re
from pathlib import Path
path = Path(snip.v.text)
content = path.read_text()
snip.rv = '\n'.join(re.findall(r'foo.*bar', content))
`
Related
I have a little homework webpage. I'm trying to automate the production of the webpage each week.
I know very little about this. Wednesday I asked about importing Python functions that I made. I think I have grasped the concept. I've tested everything in Idle. All the modules work.
In my Python shell, (I use Idle in Ubuntu), everything does what I want.
I first append the paths:
for i in range(0, len(pyPaths)):
sys.path.append(pyPaths[i])
then import the modules:
from makeRBsInlineV1 import makeHTMLrbsNums
from makeCheckboxesInlineV1 import makeHTMLCBs
from makeDropdownboxesInlineV1 import makeDropdownboxes
from createhtmlTableInlineV1 import makeHTMLtable
from makeRBsInlineV2 import makeHTML_RBs
from readLinesTextboxesInlineV1 import readLinesmakeTBs
from makeThankyouPHPInlineV1 import makeThankyouPHP
All these modules return a text string which is a mixture of html tags + my text. It displays nicely in Firefox.
In Idle I just write, for example:
myString = readLinesTextboxesInlineV3()
it asks me a few questions and off it goes. Afterwards, myString is ready to be put in the webpage text string.
However, in bash, I cannot write
myString = readLinesTextboxesInlineV3()
in bash, I cannot write
myString = input('Enter the name of the module you want. ')
and then enter,
readLinesTextboxesInlineV3()
because then myString is just the input text, not the function.
Each week things are different, I may need to run 2 or more of the modules, add the result strings, then write them in the webpage text string at the correct place.
I run this in a
while True:
loop, so I can add strings from various modules.
For any given week, I don't know which module I want to use, so I make them all available.
I have a list of all the modules:
pyFiles = ['makeCheckboxesInlineV1()', 'dropdownboxesInlineV1()',
'createhtmlTableInlineV1()', 'makeRBsInlineV2()',
'readLinesTextboxesInlineV3()', 'makeThankyouPHPInlineV1()']
How do I assign myString to any 1 of the modules above when I run makeWebpage.py in bash?
I tried this:
pyFiles = [makeHTMLCBs(), makeDropdownboxes(), makeHTMLtable(), makeHTML_RBs(), readLinesmakeTBs(), makeThankyouPHP()]
Declare a list of the functions. Trouble is, as soon as I do that, Python wants to run the first function immediately. I was hoping I could enter a number and run say:
myString = pyFiles[3]
The best solution for you is to add arguments to your python script that can be added as flag to your command line.
This way you could call your script like the following from the shell (example):
python makeWebpage.py --module "makeCheckboxesInlineV1"
Python standard library provide argparse module for that specific need. It's really easy to handle and transform shell argument into python variable.
I recommend that you read that blog post which I found myself really useful. The part you need the most is What about argparse?
Add something like this in your main:
parser = argparse.ArgumentParser()
group = parser.add_mutually_exclusive_group()
group.add_argument('-m', '--module', action='store_true')
args = parser.parse_args()
module = args.module # The variable module now is a String containing "makeCheckboxesInlineV1"
I want to extract IP addresses present in various files in a folder. I am making use of Python to invoke OS(linux) commands such as strings, grep to achieve that.
Here is the code I have-
p1 = subprocess.Popen(['strings -a -f /root/Downloads/Apps/androidproject/*'],shell=True, stdout=subprocess.PIPE)
#p2 = subprocess.Popen(["grep", "-E","10.1.1"],stdin=p1.stdout,stdout=subprocess.PIPE)
p2 = subprocess.Popen(["grep", "-E","'((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)'"],stdin=p1.stdout,stdout=subprocess.PIPE)
#p1.stdout.close()
out = p2.communicate()[0]
print "The IPs are:\n",out
The problem I am facing is that Python is not able to evaluate the RE expression I have specified to extract IP addresses from a set of text. I have verified the following things-
The RE expression is correct and works standalone,
The script is able to find/grep text which is explicitly provided like the line I have in which I am looking for IP's starting from 10.1.1
The problem lies in running the RE expression on the strings output (in the code execution) and am unable to figure out whats wrong. Could use some help.
P.S. I am open to learning an easier, better way to achieve this as well if anyone can suggest.
Thanks everyone!
Say I have the following HTML script:
<head>$name</head>
And I have the following shell script which replaces the variable in the HTML script with a name
#/bin/bash
report=$(cat ./a.html)
export name=$(echo aakash)
bash -c "echo \"$report\""
This works.
Now I have to implement the shell script in Python so that I am able to replace the variables in the HTML file and output the replaced contents in a new file. How do I do it?
An example would help. Thanks.
It looks like you're after a templating engine, but if you wanted a straight forward, no thrills, built into the standard library, here's an example using string.Template:
from string import Template
with open('a.html') as fin:
template = Template(fin.read())
print template.substitute(name='Bob')
# <head>Bob</head>
I thoroughly recommend you read the docs especially regarding escaping identifier names and using safe_substitute and such...
with open('a.html', 'r') as report:
data = report.read()
data = data.replace('$name', 'aakash')
with open('out.html', 'w') as newf:
newf.write(data)
Firstly you could save your html template like:
from string import Template
with open('a.html') as fin:
template = Template(fin.read())
Then if you want to substitute variables one at a time, you need to use safe_substitute and cast the result to a template every time. This wont return a key error even when a key value is not specified.
Something like:
new=Template(template.safe_substitute(name="Bob"))
After this , the new template is new , which needs to be modified again if you would want.
I am trying to execute the find command in a python script, using a for loop to pass a variable index determining the specific file name to find. I am using the following syntax, which in python returns an empty set, however works in the terminal:
for j in [1,2,3,5]:
file_name = cmd.getoutput('find . -type f -name "*${j}-xyz.stc" -printf "%f\n"')
Obviously, the variable is not being passed to the find expression in my python code, but how can I remedy that? Any suggestions are appreciated.
variables aren't expanded in python the same as they are in bash. You probably want:
command = r'find . -type f -name "*{0}-xyz.stc" -printf "%f\n"'.format(j)
file_name = cmd.getoutput(command)
Also note that the commands module is deprecated in favor of subprocess. Finally, it should probably be pointed out that you could write this function in python without relying on find if you used os.walk in conjunction with glob.glob.
untested, but something like this should be close ...
import os
import glob
def find_files(glob_expr):
for root,_,_ in os.walk(os.curdir):
for fname in glob.iglob(os.path.join(os.curdir,root,glob_expr)):
yield fname
for i in (1,2,3,4):
print (list(find_files('{0}-xyz.stc'.format(i))))
file_name = cmd.getoutput('find . -type f -name "*%i-xyz.stc" -printf "%%f\n"' % (j))
Passing filenames in a string to the shell is unsafe (leads to potentially security-impacting bugs). Best practice is to pass an explicit argv list:
import subprocess
for j in range(1, 6):
file_name = subprocess.check_output(['find', '.', '-type', 'f', '-name',
'*%s-xyz.stc' % (j,),
'-printf', '%f\\n'])
If you really care about correctness (and you should!), use '%f\\0' as your format string, and expect your outputs to be NUL-separated. Otherwise, you can't tell the difference between a file with a newline in its name and two files returned.
To appreciate the importance, consider the case where an attacker can persuade software running on your system to create a file named like so:
/your/top/dir/$'\n'/etc/passwd$'\n'/1-xyz.stc
If you treat each line returned by find as a filename, you would consider /etc/passwd to be part of your returned values -- a very bad thing if you then present this data to the user, delete it, etc.
I'm having trouble in my python script, and I don't understand it :
subprocess.call(['convert', file, '-crop', '80x10+90+980', '+repage', 'test.jpg'])
Returns "invalid argument - -crop"
But if I run this from the command line, it works fine :
convert test.jpg -crop 80x10+90+980 +repage test.jpg
What am I missing here ?
Is there more than one convert in the system? Try an absolute path to the command you want?
What about using the python image library instead? That seems much more reliable than to call a subprocess (especially for error handling...).
file is a _____builtin_____ class. Overriding it may produce unwanted results. Try using a different variable name.
I've actually tried your code:
>>> import subprocess
>>> subprocess.call(['convert', 'capa.jpg', '-crop', '80x10+90+980', '+repage', 'capa2.jpg'])
0
>>>
And it works for me!
So you must have something wrong, somewhere else. Check our assumptions again.