Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

Hi let's say I have a file that looks like this

<jack,
john.
................
,joe
..........Jen..
>Tom
Edwa4rd
4Tim
Richard

How do I turn this into a clean list like

jack
John
joe
Jen
Tom
Tim
Richard

Notice that Edward is not in the list

Using linux commands? Probably grep and/or sed

share|improve this question
    
Are you interested in Edwa and rd? –  Ignacio Vazquez-Abrams May 5 '12 at 5:56
    
I don't think it's possible to discard Edward entirely without a dictionary. –  Dennis May 5 '12 at 5:57
    
If it's impossible, then let's discard Edward and Tim, I don't really understand why it's impossible though, can't I do (if number in the middle then not a word) or something like that with regex? I'm also able to run multiple commands doesn't have to be one in case that helps –  user893730 May 5 '12 at 6:08
3  
"If number in the middle": yes, but it is not possible to distinguish between "Edwa4rd" and e.g. "Lisa7anna" without knowing all valid names beforehand in some dictionary. And is "Mary0anne" one invalid (Maryanne) or two valid (Mary, Anne) names? That's the problem that the earlier commenters pointed at. –  Daniel Andersson May 5 '12 at 12:13
add comment

3 Answers 3

Try egrep -o '[A-Za-z](.*[A-Za-z])?' < infile | egrep -o '[A-Za-z]+' > outfile for your example.

The first part picks out name-like things (must start with a letter and end with a letter, but may contain anything between them), and then the second egrep filters us down to just the names which are all-letters.

Looking at this, I can already see several avenues on how to create an input that would cause these expressions to fail and not match exactly the correct stuff (well, this will match as it's written to, but you've left ambiguities-- How should ..Richard..<Tim?.. be handled?), but it was easy to put this together based upon the input data-- shell scripting is often less about 100% mathematical correctness for all possible inputs, but rather knowing your input domain and getting the job done with expressions and commands that work well enough for the input you're having to process.

share|improve this answer
    
With .Net or Java or similar, that works quite well. Something similar can be done with sed on the command line. –  Darth Android May 5 '12 at 6:52
add comment

The regex ^[^a-zA-Z]*([a-zA-Z]+)[^a-zA-Z]*$ should work.

  1. ^ matches beginning of the line
  2. [^a-zA-Z]* matches zero or more occurrences of a non-letter
  3. [a-zA-Z]+ matches one or more occurrences of a letter
  4. [^a-zA-Z]* matches zero or more occurrences of a non-letter
  5. $ matches end of the line

So, it will ignore leading and following non-letters in a line and only match if there's no non-letter between the first letter and last letter.

The parenthesis indicates a capture group, which is the part we want to extract and print. I originally wrote and tested this for .NET, but here's a sed command. Don't ask me how sed works, I have no idea.

sed -rn 's/^[^a-zA-Z]*([a-zA-Z]+)[^a-zA-Z]*$/\1/p' inputfile

Instead of printing, you can write directly to an output file:

sed -rn 's/^[^a-zA-Z]*([a-zA-Z]+)[^a-zA-Z]*$/\1/w outputfile' inputfile
share|improve this answer
    
This will not handle lines which contain no letters, allowing them to pass into the output unmodified. –  Darth Android May 5 '12 at 18:12
    
@DarthAndroid It works on his example... the third line of which contains no letters. [a-zA-Z]+ should match at least one letter. It also works on a blank line. Tested with GNU sed 4.2.1. –  Bob May 6 '12 at 3:36
add comment

Use grep -o '[[:alpha:]]\+' to extract out all the "words".

jack
john
joe
Jen
Tom
Edwa
rd
Tim
Richard

It's then up to you to determine which ones are names and which are just sequences of letter.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.