Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people, just like you, are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
Solved

Powershell program to read file and do substitutions

Posted on 2013-05-20
13
349 Views
Last Modified: 2013-05-21
I am looking for a powershell program that will prompt for the name and open a .txt file. The .txt file has approximately 250 vertical bar character (|) delimited fields on each line. The number of lines varies. A sample of this file is attached as sample.txt.

The program needs to examine each line and look for the string 11300 in field 167 (as counted by the vertical bar characters). If field 167 does not equal 11300 write the unchanged line to an output file (inputfilename.out.txt) and go to the next line. If field 167 does contain 11300,then look in field 191 for a two character string. Using that two character string, look up in a table (can be a separate file or an array in the program, your choice), to obtain two digits to append to the string in field 167 (a sample of the table/array is attached as substitution.pdf) and write the line with that change to the output file. Continue with each line until the end of file is reached.

For example, if 11300 is found in field 167, and field 191 has AT in it, then field 167 should be written out as 1130010.

thanks....
sample.txt
substitution.pdf
0
Comment
Question by:carlmd
  • 5
  • 4
  • 4
13 Comments
 
LVL 42

Expert Comment

by:sedgwick
ID: 39181507
i used map.txt which has the mapping from your pdf file.
the output of the script is also attached.
cls
$map = @{}
$outputfile = "c:\temp\inputfilename.out.txt"
ri $outputfile 
function createMap{
	gc c:\temp\map.txt |%{
		$tokens = $_ -split ' '
		$map[$tokens[0]] = $tokens[1]
	}
}

function parseFile{
	gc c:\temp\sample.txt |%{
		$tokens = $_.Split('|')
		if($tokens[166] -eq 11300){
			$code = $tokens[190]
			$digits = $map[$code]
			"11300{0}" -f $digits | Out-File $outputfile -Append
		}else{
			$tokens -join "|" | Out-File $outputfile -Append
		}
	}
}

createMap
parseFile

Open in new window

map.txt
inputfilename.out.txt
0
 
LVL 69

Expert Comment

by:Qlemo
ID: 39181677
One improvement: Line 20 shouldn't rejoin the line, instead we still have the original line in $_:
			$_ | Out-File $outputfile -Append

Open in new window

I would also remove both
   | Out-File $outputfile -Append
and instead write the result in one go in line 22:
	}  | Out-File $outputfile

Open in new window

which saves a lot of file operations if the text file contains a lot of lines.
0
 
LVL 20

Author Comment

by:carlmd
ID: 39181679
Looks close...

"If field 167 does not equal 11300 write the unchanged line to an output file (inputfilename.out.txt) and go to the next line"

The intent was that if 11300 was not found, the input line is simply written to the output file unchanged. You appear to be writing out only that one field and not the entire input line.
0
Is Your AD Toolbox Looking More Like a Toybox?

Managing Active Directory can get complicated.  Often, the native tools for managing AD are just not up to the task.  The largest Active Directory installations in the world have relied on one tool to manage their day-to-day administration tasks: Hyena. Start your trial today.

 
LVL 42

Expert Comment

by:sedgwick
ID: 39181697
I do output the whole line check line 20.
Also ive attached the output txt file.
0
 
LVL 20

Author Comment

by:carlmd
ID: 39181719
The output.txt.file that is attached has 8 lines, the two with the substitution are correct, but five only have the one field on them. Maybe you attached the wrong file? Take a look at the attachment....
0
 
LVL 42

Expert Comment

by:sedgwick
ID: 39181743
U right my bad. Fixing...
0
 
LVL 69

Assisted Solution

by:Qlemo
Qlemo earned 100 total points
ID: 39181744
It should be vice versa: All substitutions are wrong, only outputting the replaced field instead of the complete line. This should work:
cls
$map = @{}
$outputfile = "c:\temp\inputfilename.out.txt"
ri $outputfile 
function createMap{
  gc c:\temp\map.txt | % {
    $tokens = $_ -split ' '
    $map[$tokens[0]] = $tokens[1]
  }
}

function parseFile{
  gc c:\temp\sample.txt |% {
    $tokens = $_.Split('|')
    if($tokens[166] -eq 11300) {
      $tokens[166} += $map[$tokens[190]]
      $tokens -join '|'
    } else {
      $_
    }
  } | Out-File $outputfile
}

createMap
parseFile

Open in new window

0
 
LVL 42

Expert Comment

by:sedgwick
ID: 39182036
cls
$map = @{}
$outputfile = "c:\temp\inputfilename.out.txt"
ri $outputfile -ErrorAction SilentlyContinue
function createMap{
	gc c:\temp\map.txt |%{
		$tokens = $_ -split ' '
		$map[$tokens[0]] = $tokens[1]
	}
}

function parseFile{
	gc c:\temp\sample.txt |%{
		$line = $_
		$tokens = $line.Split('|')
		if($tokens[166] -eq 11300){
			$line = $line.Replace("11300", ("11300{0}" -f $map[$tokens[190]]))
		}
		$line | Out-File $outputfile -Append
	}
}

createMap
parseFile

Open in new window

0
 
LVL 69

Expert Comment

by:Qlemo
ID: 39182159
sedgwick,

To make it more safe I would use
			$line = $line.Replace("|11300|", ("|11300{0}|" -f $map[$tokens[190]]))

Open in new window

but that still might replace a different column.
0
 
LVL 20

Author Comment

by:carlmd
ID: 39183949
Ok, I verified that the script works but I need it to prompt for filename of input file and use that to create output file name.

For example:

Input file name:   july.txt

then create the output file as july.out.txt
0
 
LVL 42

Accepted Solution

by:
sedgwick earned 400 total points
ID: 39183972
cls
$inputfile = Read-Host 'Enter Input file name:'
$outputfile = $inputfile.Replace(".", ".out.");
if([IO.File]::Exists($inputfile) -ne $true) {
	write-output "$inputfile could not be found"
	return
}

$map = @{}
ri $outputfile -ErrorAction SilentlyContinue
function createMap{
	gc c:\temp\map.txt |%{
		$tokens = $_ -split ' '
		$map[$tokens[0]] = $tokens[1]
	}
}

function parseFile{
	gc $inputfile |%{
		$line = $_
		$tokens = $line.Split('|')
		if($tokens[166] -eq 11300){
			$line = $line.Replace("11300", ("11300{0}" -f $map[$tokens[190]]))
		}
		$line | Out-File $outputfile -Append
	}
}

createMap
parseFile

Open in new window

0
 
LVL 20

Author Closing Comment

by:carlmd
ID: 39184857
Works like a champ!
0
 
LVL 69

Expert Comment

by:Qlemo
ID: 39185839
Please note http:#a39182159. The replacement is not safe, a different column might get changed.
0

Featured Post

Best Practices: Disaster Recovery Testing

Besides backup, any IT division should have a disaster recovery plan. You will find a few tips below relating to the development of such a plan and to what issues one should pay special attention in the course of backup planning.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

This script checks a path to see if a folder exists. If the folder does exist you will get output "The folder has previously been created. No action taken" If not it will create the folder. Then adds one user modify permission to the folder. It …
In this previous article (https://oddytee.wordpress.com/2016/05/05/provision-new-office-365-user-and-mailbox-from-exchange-hybrid-via-powershell/), we made basic license assignments to users in O365. When I say basic, the method is the simplest way …
The viewer will learn how to dynamically set the form action using jQuery.
In this fourth video of the Xpdf series, we discuss and demonstrate the PDFinfo utility, which retrieves the contents of a PDF's Info Dictionary, as well as some other information, including the page count. We show how to isolate the page count in a…

791 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question