change the sed() parser to split out the command (aisdxX) from the args
change the parseQuotedArgs() to return a tuple (pattern, filename)
This commit is contained in:
@@ -169,7 +169,7 @@ If the single-letter command is preceded by a number or number-range, then the e
|
|||||||
|
|
||||||
The `i/a/d` commands should be preceeded by a line number, or range; `sed()` will *insert*, *append* or *delete* once for each line in the range.
|
The `i/a/d` commands should be preceeded by a line number, or range; `sed()` will *insert*, *append* or *delete* once for each line in the range.
|
||||||
|
|
||||||
The ``x/X` patterns are wrapped in a pair of delimiter characters, typically /, although any other character is allowed (except space or any of `\^$()[]`). Valid X commands are:
|
The ``x/X` patterns are wrapped in a pair of delimiter characters, typically `/`, although almost any other character is allowed other than space or one of `\^$()[]`. Valid X commands are:
|
||||||
|
|
||||||
```
|
```
|
||||||
x/abcd/
|
x/abcd/
|
||||||
@@ -177,7 +177,7 @@ x/abcd/
|
|||||||
x!ratio x/y!
|
x!ratio x/y!
|
||||||
```
|
```
|
||||||
|
|
||||||
Similarly, the s patterns are wrapped in a triplet of delimiter characters, typcially / also. If the search pattern has `()` groups, the replace pattern can refer to them with ``\1 \2`,etc. Valid 's' commands are
|
Similarly, the s patterns are wrapped in a triplet of delimiter characters, typcially / also. If the search pattern has `()` groups, the replace pattern can refer to them with ``\1 \2`,etc. This `sed()` assumed the `g` suffix, it replaces multiple occurrences on a line. Valid 's' commands are
|
||||||
|
|
||||||
```
|
```
|
||||||
s/toronto/Toronto/
|
s/toronto/Toronto/
|
||||||
@@ -267,6 +267,8 @@ In its present form, the module has these limitations:
|
|||||||
* with sed, lines are parsed and saved one-line-at-a-time, so pattern matching to \n and \r does not work; sed cannot work over line boundaries
|
* with sed, lines are parsed and saved one-line-at-a-time, so pattern matching to \n and \r does not work; sed cannot work over line boundaries
|
||||||
* this simple shell is different than [mpfshell](https://github.com/wendlers/mpfshell) in that this shell runs entirely on the target device. There is no allowance in this shell for transferring files in/out of the target.
|
* this simple shell is different than [mpfshell](https://github.com/wendlers/mpfshell) in that this shell runs entirely on the target device. There is no allowance in this shell for transferring files in/out of the target.
|
||||||
* after a restart of your *MicroPython* board, you can invoke the shell with `import tf`; if you `^C` out of the shell, the second invocation of `tf` will have to be `import tf` followed by `tf.main()`, since the python interpreter caches the module and only loads it once per restart; you can intentionally restart the REPL prompt by hitting `^D`
|
* after a restart of your *MicroPython* board, you can invoke the shell with `import tf`; if you `^C` out of the shell, the second invocation of `tf` will have to be `import tf` followed by `tf.main()`, since the python interpreter caches the module and only loads it once per restart; you can intentionally restart the REPL prompt by hitting `^D`
|
||||||
|
* for the `sed()` function and command line, the
|
||||||
|
[search](https://docs.micropython.org/en/latest/library/ure.html) pattern can have wildcards like ``\s`, `\w` and `\d`. The replace pattern cannot have *any* of these, and can only have `\0`, `\1`, etc
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
|
|||||||
36
tf.py
36
tf.py
@@ -43,10 +43,10 @@ def grep(filename, pattern, numbers=False):
|
|||||||
def sed(filename, sed_cmd, bak_ext=".bak"):
|
def sed(filename, sed_cmd, bak_ext=".bak"):
|
||||||
# parse the sed_cmd
|
# parse the sed_cmd
|
||||||
# group 1,3 are the n-start, n-end group 4 is command: aidsxX
|
# group 1,3 are the n-start, n-end group 4 is command: aidsxX
|
||||||
a=re.search("^(\d*)([,-](\d+|\$))?\s*([sdaixX].*)",sed_cmd)
|
a=re.search("^(\d*)([,-](\d+|\$))?\s*([sdaixX])(.*)",sed_cmd)
|
||||||
if not a:
|
if not a:
|
||||||
raise ValueError("sed() failed; pattern must be a number-range followed by one of sdaixX; no changes applied")
|
raise ValueError("sed() failed; pattern must be a number-range followed by one of sdaixX; no changes applied")
|
||||||
cmd=a.group(4)
|
op,args=a.group(4),a.group(5)
|
||||||
|
|
||||||
s,e=1,1000000
|
s,e=1,1000000
|
||||||
if a.group(1):
|
if a.group(1):
|
||||||
@@ -54,26 +54,25 @@ def sed(filename, sed_cmd, bak_ext=".bak"):
|
|||||||
if a.group(3):
|
if a.group(3):
|
||||||
e=1000000 if a.group(3)=='$' else int(a.group(3))
|
e=1000000 if a.group(3)=='$' else int(a.group(3))
|
||||||
|
|
||||||
op=cmd[0]
|
|
||||||
if op in "aid" and e-s==1000000:
|
if op in "aid" and e-s==1000000:
|
||||||
raise ValueError("sed(a/i/d) should have a line number")
|
raise ValueError("sed(a/i/d) should have a line number")
|
||||||
#print("sed command parser of <{}> returned {} {} {}".format(op,cmd,a.group(1),a.group(3)))
|
#print("sed command parser of <{}> returned {} {} {}".format(op,cmd,a.group(1),a.group(3)))
|
||||||
if op in "sxX":
|
if op in "sxX":
|
||||||
if len(cmd)<2 or cmd[1] in "\^$()[]":
|
if len(args)<2 or args[0] in "\^$()[]":
|
||||||
raise ValueError("invalid sed argument: {}".format(cmd))
|
raise ValueError("invalid sed argument: "+op+args)
|
||||||
dl=cmd[1]
|
dl=args[0]
|
||||||
if op=='s':
|
if op=='s':
|
||||||
gs=re.search("s"+dl+"([^"+dl+"]*)"+dl+"([^"+dl+"]*)"+dl,cmd)
|
gs=re.search(dl+"([^"+dl+"]*)"+dl+"([^"+dl+"]*)"+dl,args)
|
||||||
else:
|
else:
|
||||||
gs=re.search("[xX]"+dl+"([^"+dl+"]*)"+dl,cmd)
|
gs=re.search(dl+"([^"+dl+"]*)"+dl,args)
|
||||||
if not gs:
|
if not gs:
|
||||||
raise ValueError("invalid sed search pattern: {}".format(cmd))
|
raise ValueError("invalid sed search pattern: "+op+args)
|
||||||
ss=gs.group(1)
|
ss=gs.group(1)
|
||||||
if op=='s':
|
if op=='s':
|
||||||
r=gs.group(2)
|
r=gs.group(2)
|
||||||
sp=re.compile(ss)
|
sp=re.compile(ss)
|
||||||
|
|
||||||
extra=a.group(4)[1:] + '\n'
|
args=args + '\n'
|
||||||
|
|
||||||
try:
|
try:
|
||||||
os.rename(filename,filename+bak_ext)
|
os.rename(filename,filename+bak_ext)
|
||||||
@@ -95,7 +94,7 @@ def sed(filename, sed_cmd, bak_ext=".bak"):
|
|||||||
continue # delete line
|
continue # delete line
|
||||||
if op=='i' and m:
|
if op=='i' and m:
|
||||||
#print("insert a line before {} <{}>".format(i,extra))
|
#print("insert a line before {} <{}>".format(i,extra))
|
||||||
g.write(extra)
|
g.write(args)
|
||||||
h+=1
|
h+=1
|
||||||
if op in "aids":
|
if op in "aids":
|
||||||
g.write(lin)
|
g.write(lin)
|
||||||
@@ -104,7 +103,7 @@ def sed(filename, sed_cmd, bak_ext=".bak"):
|
|||||||
h+=1
|
h+=1
|
||||||
if op=='a' and m:
|
if op=='a' and m:
|
||||||
#print("append a line after {} <{}>".format(i,extra))
|
#print("append a line after {} <{}>".format(i,extra))
|
||||||
g.write(extra)
|
g.write(args)
|
||||||
h+=1
|
h+=1
|
||||||
#f.write("--file modifed by sed()--\n")
|
#f.write("--file modifed by sed()--\n")
|
||||||
return (i, h)
|
return (i, h)
|
||||||
@@ -139,15 +138,16 @@ def _help():
|
|||||||
ext_cmd('help')
|
ext_cmd('help')
|
||||||
|
|
||||||
def parseQuotedArgs(st):
|
def parseQuotedArgs(st):
|
||||||
|
#returns (pattern,file)
|
||||||
st=st.strip()
|
st=st.strip()
|
||||||
if st[0]=="'":
|
if st[0]=="'":
|
||||||
p=re.search("'(.*?[^\\\\])'",st)
|
p=re.search("'(.*?[^\\\\])'\s*(\S*)",st)
|
||||||
if not p:
|
if not p:
|
||||||
print("error in quoted pattern:",st)
|
print("error in quoted pattern:",st)
|
||||||
return
|
return
|
||||||
return p.group(1)
|
return p.group(1),p.group(2)
|
||||||
else:
|
else:
|
||||||
return st.split()[0]
|
return st.split(None,1)
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
print("Simple shell: cp/copy mv/move rm/del cat/list cd dir/ls mkdir rmdir grep sed help")
|
print("Simple shell: cp/copy mv/move rm/del cat/list cd dir/ls mkdir rmdir grep sed help")
|
||||||
@@ -183,9 +183,9 @@ def main():
|
|||||||
continue
|
continue
|
||||||
try:
|
try:
|
||||||
if op=='grep':
|
if op=='grep':
|
||||||
grep(rp[-1],p,numbers=True)
|
grep(p[1],p[0],numbers=True)
|
||||||
else:
|
else:
|
||||||
r=sed(rp[-1],p)
|
r=sed(p[1],p[0])
|
||||||
if r:
|
if r:
|
||||||
print("Lines processed: {} Lines modifed: {}".format(*r))
|
print("Lines processed: {} Lines modifed: {}".format(*r))
|
||||||
except (ValueError, OSError) as e:
|
except (ValueError, OSError) as e:
|
||||||
@@ -216,7 +216,7 @@ def main():
|
|||||||
except IndexError:
|
except IndexError:
|
||||||
print("not enough argments; check syntax with 'help'")
|
print("not enough argments; check syntax with 'help'")
|
||||||
except OSError:
|
except OSError:
|
||||||
print("file/folder not found or cannot be writtencd")
|
print("file/folder not found or cannot be written")
|
||||||
gc.collect()
|
gc.collect()
|
||||||
|
|
||||||
if __name__=="tf":
|
if __name__=="tf":
|
||||||
|
|||||||
Reference in New Issue
Block a user