Matthew Downey
Matthew Downey

Reputation: 259

Parsing strings in python

So my problem is this, I have a file that looks like this:

[SHIFT]this isrd[BACKSPACE][BACKSPACE] an example file[SHIFT]1

This would of course translate to

' This is an example file!'

I am looking for a way to parse the original content into the end content, so that a [BACKSPACE] will delete the last character(spaces included) and multiple backspaces will delete multiple characters. The [SHIFT] doesnt really matter as much to me. Thanks for all the help!

Upvotes: 5

Views: 5409

Answers (5)

inspectorG4dget
inspectorG4dget

Reputation: 114035

This does exactly what you want:

def shift(s):
    LOWER = '`1234567890-=[];\'\,./'
    UPPER = '~!@#$%^&*()_+{}:"|<>?'

    if s.isalpha():
        return s.upper()
    else:
        return UPPER[LOWER.index(s)]

def parse(input):
    input = input.split("[BACKSPACE]")
    answer = ''
    i = 0
    while i<len(input):
        s = input[i]
        if not s:
            pass
        elif i+1<len(input) and not input[i+1]:
            s = s[:-1]
        else:
            answer += s
            i += 1
            continue
        answer += s[:-1]
        i += 1

    return ''.join(shift(i[0])+i[1:] for i in answer.split("[SHIFT]") if i)

>>> print parse("[SHIFT]this isrd[BACKSPACE][BACKSPACE] an example file[SHIFT]1")
>>> This is an example file!

Upvotes: 1

Inaimathi
Inaimathi

Reputation: 14063

If you don't care about the shifts, just strip them, load

(defun apply-bspace ()
  (interactive)
  (let ((result (search-forward "[BACKSPACE]")))
    (backward-delete-char 12)
    (when result (apply-bspace))))

and hit M-x apply-bspace while viewing your file. It's Elisp, not python, but it fits your initial requirement of "something I can download for free to a PC".

Edit: Shift is trickier if you want to apply it to numbers too (so that [SHIFT]2 => @, [SHIFT]3 => #, etc). The naive way that works on letters is

(defun apply-shift ()
  (interactive)
  (let ((result (search-forward "[SHIFT]")))
    (backward-delete-char 7)
    (upcase-region (point) (+ 1 (point)))
    (when result (apply-shift))))

Upvotes: 1

Joe Kington
Joe Kington

Reputation: 284870

Here's one way, but it feels hackish. There's probably a better way.

def process_backspaces(input, token='[BACKSPACE]'):
    """Delete character before an occurence of "token" in a string."""
    output = ''
    for item in (input+' ').split(token):
        output += item
        output = output[:-1]
    return output

def process_shifts(input, token='[SHIFT]'):
    """Replace characters after an occurence of "token" with their uppecase 
    equivalent. (Doesn't turn "1" into "!" or "2" into "@", however!)."""
    output = ''
    for item in (' '+input).split(token):
        output += item[0].upper() + item[1:]
    return output

test_string = '[SHIFT]this isrd[BACKSPACE][BACKSPACE] an example file[SHIFT]1'
print process_backspaces(process_shifts(test_string))

Upvotes: 1

Gonzalo Larralde
Gonzalo Larralde

Reputation: 3541

You need to read the input, extract the tokens, recognize them, and give a meaning to them.

This is how I would do it:

# -*- coding: utf-8 -*-

import re

upper_value = {
    1: '!', 2:'"',
}

tokenizer = re.compile(r'(\[.*?\]|.)')
origin = "[SHIFT]this isrd[BACKSPACE][BACKSPACE] an example file[SHIFT]1"
result = ""

shift = False

for token in tokenizer.findall(origin):
    if not token.startswith("["):
        if(shift):
            shift = False
            try:
                token = upper_value[int(token)]
            except ValueError:
                token = token.upper()

        result = result + token
    else:
        if(token == "[SHIFT]"):
            shift = True
        elif(token == "[BACKSPACE]"):
            result = result[0:-1]

It's not the fastest, neither the elegant solution, but I think it's a good start.

Hope it helps :-)

Upvotes: 0

gahooa
gahooa

Reputation: 137522

It seems that you could use a regular expression to search for (something)[BACKSPACE] and replace it with nothing...

re.sub('.?\[BACKSPACE\]', '', YourString.replace('[SHIFT]', ''))

Not sure what you meant by "multiple spaces delete multiple characters".

Upvotes: 0

Related Questions