I am using the script below which creates a search/replace list and applies it to another list.
How can I tell it to ignore partial returns, so that it will only swap if the entire value is located?
Thanks
set uniqueText to do shell script "awk -F'" & tab & "' 'BEGIN{getline}{print $14}' " & quoted form of POSIX path of filePath
set uniqueList to paragraphs of (do shell script " awk -F'" & tab & "' 'BEGIN{getline}{print $1\"\\t\"$2}' " & quoted form of POSIX path of filePath2)
set uniqueList2 to my replace_chars(uniqueText, uniqueList)
to replace_chars(t, L2)
set tid to text item delimiters
set tc to count L2
repeat with i from 1 to tc
set text item delimiters to tab
set {toFind, toReplace} to text items of (item i of L2)
set text item delimiters to toFind
set {L, text item delimiters} to {text items of t, toReplace}
set t to L as text
end repeat
set text item delimiters to tid
return paragraphs of t
end replace_chars
Below is the full script. It is a mess, because I am not very good at this, but it works… sort of.
The script will pull the data from column 14 of a tab delimited text file in folder ‘RawData’. Then it will pull the first 2 columns of data from another tab delimited text file in folder ‘InventoryList’ to use as search and replace values. It will then apply the search/replace and save the results as a tab delimited text file in folder “FinishedFile”. It does require a blank text document (Finished_File.txt) to already be present at filePath3 before executing.
The problem I am having is that when I have the search replace values below:
So instead of swapping out AMZ-CLIC360-MAR-CV-6P to the correct value, it using the replace value for AMZ-CLIC360-MAR-CV-6 and then retaining the “P”.
Is there a simple way to stop the script behaving this way?
tell application "Finder"
set filePath to (first file of folder "Macintosh HD:RawData") as alias
set filePath2 to (first file of folder "Macintosh HD:InventoryList") as alias
end tell
set fileRefr to (open for access filePath)
set theText to (read fileRefr)
set textList to paragraphs of theText
close access fileRefr
set theCNT to (count of textList) - 1
set finalCNT to ((theCNT - 1))
set uniqueText to do shell script "awk -F'" & tab & "' 'BEGIN{getline}{print $14}' " & quoted form of POSIX path of filePath
set uniqueList to paragraphs of (do shell script " awk -F'" & tab & "' 'BEGIN{getline}{print $1\"\\t\"$2}' " & quoted form of POSIX path of filePath2)
set uniqueList2 to my replace_chars(uniqueText, uniqueList)
to replace_chars(t, L2)
set tid to text item delimiters
set tc to count L2
repeat with i from 1 to tc
set text item delimiters to tab
set {toFind, toReplace} to text items of (item i of L2)
set text item delimiters to toFind
set {L, text item delimiters} to {text items of t, toReplace}
set t to L as text
end repeat
set text item delimiters to tid
return paragraphs of t
end replace_chars
tell application "Finder"
set filePath3 to "Macintosh HD:Finished_File.txt"
set fileRefr3 to (open for access filePath3)
set theText to (read fileRefr3)
set textList to paragraphs of theText
close access fileRefr3
set finalDoc to {}
set end of finalDoc to textList
repeat with i from 1 to finalCNT
try
set thisParagraph to first word of item i of uniqueList2
set end of finalDoc to thisParagraph
end try
end repeat
end tell
set filename to "Finished_File.txt"
set {tids, text item delimiters} to {text item delimiters, return}
set finalText to finalDoc as text
set text item delimiters to tids
set theFile to filePath3
set theNewFile to "Macintosh HD:FinishedFile:" & filename
set fileRef to (open for access theFile with write permission)
set filesEOF to get eof fileRef
set dataIn to finalText
close access fileRef
set dataOut to dataIn
set fileRef to (open for access theNewFile with write permission)
set eof of fileRef to 0
write dataOut to fileRef
set eof of fileRef to (length of dataOut)
close access fileRef
Indeed…
Let’s see if I can figure out what you want (which may be different from what your script is doing ;)).
you have a data file (CSV) where you want to work on column 14.
you have a support file (CSV) where column 1 contain search terms, and column 2 contains replacement values.
The script should go through the data in column 14, and find-and-replace using the data from the support file.
And that’s as far as I get. I have no idea what you want to write to the output file.
Do you want the modified data file, or just its column 14, with the modified data?
Like mr. Stone said, give us a sample of the data and support files.
Just write (a part) of the content of the file or an example to show the exact structure. Then we can provide/help with scripts based on that content and your wishes.
I’ve edited the script to show the problem clearly, I just need to share 2 files with you in order for it to work. Is there a way to attached them to these posts?
First point, I would make some changes at the structure of your script.
Your second tell application “Finder” was useless.
It’s at least bad practice to code a handler in the middle of the main code.
Here is the code edited according to these comments.
tell application "Finder"
set filePath to (first file of folder "Macintosh HD:RawData") as alias
set filePath2 to (first file of folder "Macintosh HD:InventoryList") as alias
end tell
set fileRefr to (open for access filePath)
set theText to (read fileRefr)
close access fileRefr
set textList to paragraphs of theText # MOVED
set theCNT to (count of textList) - 1
set finalCNT to ((theCNT - 1))
set uniqueText to do shell script "awk -F'" & tab & "' 'BEGIN{getline}{print $14}' " & quoted form of POSIX path of filePath
set uniqueList to paragraphs of (do shell script " awk -F'" & tab & "' 'BEGIN{getline}{print $1\"\\t\"$2}' " & quoted form of POSIX path of filePath2)
set uniqueList2 to my replace_chars(uniqueText, uniqueList)
--tell application "Finder"
set filePath3 to "Macintosh HD:Finished_File.txt"
set fileRefr3 to (open for access filePath3)
set theText to (read fileRefr3)
set textList to paragraphs of theText
close access fileRefr3
set finalDoc to {}
set end of finalDoc to textList
repeat with i from 1 to finalCNT
try
set thisParagraph to first word of item i of uniqueList2
set end of finalDoc to thisParagraph
end try
end repeat
--end tell
set filename to "Finished_File.txt"
set {tids, text item delimiters} to {text item delimiters, return}
set finalText to finalDoc as text
set text item delimiters to tids
set theFile to filePath3
set theNewFile to "Macintosh HD:FinishedFile:" & filename
set fileRef to (open for access theFile with write permission)
set filesEOF to get eof fileRef
set dataIn to finalText
close access fileRef
set dataOut to dataIn
set fileRef to (open for access theNewFile with write permission)
set eof of fileRef to 0
write dataOut to fileRef
set eof of fileRef to (length of dataOut)
close access fileRef
to replace_chars(t, L2)
set tid to text item delimiters
set tc to count L2
repeat with i from 1 to tc
set text item delimiters to tab
set {toFind, toReplace} to text items of (item i of L2)
set text item delimiters to toFind
set {L, text item delimiters} to {text items of t, toReplace}
set t to L as text
end repeat
set text item delimiters to tid
return paragraphs of t
end replace_chars
What you get is normal.
On entry you have :
“AMZ-CLIC360-MAR-CV-6
AMZ-CLIC360-MAR-CV-6P”
Stepping in your replace handler we may see that as the uniqueList contain two strings you make two pass.
At first pass the string AMZ-CLIC360-MAR-CV-6 is replaced by B013RC9A6W
so t becomes :
(B013RC9A6W
B013RC9A6WP)
at second pass, there is no longer a string to replace so you get
{“B013RC9A6W”, “B013RC9A6WP”}
If you sort the uniqueList so that the longest item to replace appear at first you will get a better result.
set source to "AMZ-CLIC360-MAR-CV-6
AMZ-CLIC360-MAR-CV-6P"
set replacements to "AMZ-CLIC360-MAR-CV-6 B013RC9A6W
AMZ-CLIC360-MAR-CV-6P B013RC9A08
AMZ-CLIC360-MAR B013RC9A6Waaa"
set uniquetext to source
set uniquelist to paragraphs of replacements
set uniquelist to my SortByLength(uniquelist)
set uniqueList2 to my replace_chars(uniquetext, uniquelist)
to replace_chars(t, L2)
set tid to text item delimiters
set tc to count L2
repeat with i from 1 to tc
set text item delimiters to tab
set {toFind, toReplace} to text items of (item i of L2)
set text item delimiters to toFind
set {L, text item delimiters} to {text items of t, toReplace}
set t to L as text
end repeat
set text item delimiters to tid
return paragraphs of t
end replace_chars
#=====
on SortByLength(my_list)
set the low_item to tab
set the sorted_list to {}
set {Otids, text item delimiters} to {text item delimiters, tab}
repeat (count my_list) - 1 times
repeat with i from 1 to (count my_list)
set this_item to item i of my_list as text
if (count text item 1 of this_item) > (count text item 1 of low_item) then
set the low_item to this_item
set the low_item_index to i
end if
end repeat
set text item delimiters to Otids
--remove the item from the list
set the edited_list to {}
repeat with z from 1 to the number of items in my_list
if z is not the low_item_index then set the end of the edited_list to item z of my_list
end repeat
--set the list to the edited version
set my_list to the edited_list
set the sorted_list to the sorted_list & the low_item
set the low_item to tab
end repeat
--add the last item in the list
set the sorted_list to the sorted_list & my_list
return the sorted_list
end SortByLength
#=====
The handler used to sort is not a very efficient one but I have no idea of the size of the uniquelist so I didn’t tried to build an efficient one.
Yvan KOENIG running El Capitan 10.11.1 in French (VALLAURIS, France) vendredi 27 novembre 2015 15:58:10
Your idea to sort the search/replace list is great but the script doesn’t work properly once I have inserted the handler.
The script I shared was pulled from an even longer (and uglier) script that I mashed together with the limited knowledge that I possess. I have rewritten it below to show where it is failing. As it needs to be re-inserted back into my other script, I really need advice on how to modify this script to work properly, rather than re-write from scratch.
Create the folders - RawData, InventoryList & FinishedFile - and set the paths in the script correctly
Place the file Finished_File.txt somewhere and set this path too.
If you then put the file (data.txt) in to both folders (RawData & InventoryList) and execute, it will run the search/replace on itself and yield a file (in folder FinishedFile) with 3 columns. 1 is the search term, 2 is the desired replace term, and 3 is the actual replaced term. As you will see, columns 2 and 3 do not always align.
If I insert your handler, the search/replace only works on a couple of the entries. Do you have any suggestions how to modify the handler so it yields the correct results?
tell application "Finder"
set filePath to (first file of folder "Macintosh HD:Users:Will:RawData") as alias
set filePath2 to (first file of folder "Macintosh HD:Users:Will:InventoryList") as alias
end tell
set fileRefr to (open for access filePath)
set theText to (read fileRefr)
set textList to paragraphs of theText
close access fileRefr
set theCNT to (count of textList) - 1
set finalCNT to ((theCNT - 1))
set uniqueText to do shell script "awk -F'" & tab & "' 'BEGIN{getline}{print $1}' " & quoted form of POSIX path of filePath
set uniqueList to {}
set dataList to every paragraph of (do shell script "cat " & quoted form of POSIX path of filePath & " | awk -F'" & tab & "' 'BEGIN{getline}{print $2}'")
set uniqueList to uniqueList & dataList
set uniqueList2 to paragraphs of (do shell script " awk -F'" & tab & "' 'BEGIN{getline}{print $1\"\\t\"$2}' " & quoted form of POSIX path of filePath2)
set uniqueList3 to my replace_chars(uniqueText, uniqueList2)
to replace_chars(t, L2)
set tid to text item delimiters
set tc to count L2
repeat with i from 1 to tc
set text item delimiters to tab
set {toFind, toReplace} to text items of (item i of L2)
set text item delimiters to toFind
set {L, text item delimiters} to {text items of t, toReplace}
set t to L as text
end repeat
set text item delimiters to tid
return paragraphs of t
end replace_chars
set filePath3 to "Macintosh HD:Users:Will:Finished_File.txt"
set fileRefr3 to (open for access filePath3)
set theText to (read fileRefr3)
set textList to paragraphs of theText
close access fileRefr3
set finalDoc to {}
set end of finalDoc to textList
repeat with i from 1 to finalCNT
try
set thisParagraph to (item i of uniqueList2 & " " & item i of uniqueList3)
set end of finalDoc to thisParagraph
end try
end repeat
end tell
set filename to "Finished_File.txt"
set {tids, text item delimiters} to {text item delimiters, return}
set finalText to finalDoc as text
set text item delimiters to tids
set theFile to filePath3
set theNewFile to "Macintosh HD:Users:Will:FinishedFile:" & filename
set fileRef to (open for access theFile with write permission)
set filesEOF to get eof fileRef
set dataIn to finalText
close access fileRef
set dataOut to dataIn
set fileRef to (open for access theNewFile with write permission)
set eof of fileRef to 0
write dataOut to fileRef
set eof of fileRef to (length of dataOut)
close access fileRef
Attached is a cleaned version of your script.
Of course, I can’t test it.
on run
set p2h to path to home folder as text
tell application "System Events"
set filePath to first file of folder (p2h & "RawData") as alias
set filePath2 to first file of folder (p2h & "InventoryList") as alias
end tell
(*
set fileRefr to (open for access filePath)
set theText to (read fileRefr)
close access fileRefr # Close access before working upon the datas.
set textList to paragraphs of theText
set theCNT to (count textList) - 1
set finalCNT to ((theCNT - 1))
*)
set finalCNT to (count paragraphs of (read filePath)) - 2
set uniqueText to do shell script "awk -F'" & tab & "' 'BEGIN{getline}{print $1}' " & quoted form of POSIX path of filePath
-- set uniqueList to paragraphs of (do shell script "cat " & quoted form of POSIX path of filePath & " | awk -F'" & tab & "' 'BEGIN{getline}{print $2}'")
set uniqueList2 to paragraphs of (do shell script " awk -F'" & tab & "' 'BEGIN{getline}{print $1\"\\t\"$2}' " & quoted form of POSIX path of filePath2)
set uniqueList3 to my replace_chars(uniqueText, uniqueList2)
(*
set filePath3 to "Macintosh HD:Users:Will:Finished_File.txt"
set fileRefr3 to (open for access filePath3)
set theText to (read fileRefr3)
close access fileRefr3
set textList to paragraphs of theText
set finalDoc to {}
set end of finalDoc to textList
*)
set filePath3 to p2h & "Finished_File.txt"
set finaldoc to paragraphs of (read file filePath3)
repeat with i from 1 to finalCNT
try
set end of finaldoc to (item i of uniqueList2 & " " & item i of uniqueList3)
end try
end repeat
--end tell
set {tids, text item delimiters} to {text item delimiters, return}
--set finalText to finaldoc as text
set dataOut to finaldoc as text
set text item delimiters to tids
--set theFile to filePath3
--set filename to "Finished_File.txt"
set theNewFile to p2h & "FinishedFile:Finished_File.txt"
--set fileRef to (open for access theFile with write permission)
-- set filesEOF to get eof fileRef # you never use it
-- set dataIn to finalText
--close access fileRef
--set dataOut to dataIn
try
set fileRef to (open for access theNewFile with write permission)
set eof of fileRef to 0
write dataOut to fileRef
--set eof of fileRef to (length of dataOut)
close access fileRef
on error
try
close access theNewFile
end try
end try
end run
#=====
# NEVER put a handler in the main flow !
to replace_chars(t, L2)
set tid to text item delimiters
set tc to count L2
repeat with i from 1 to tc
set text item delimiters to tab
set {toFind, toReplace} to text items of (item i of L2)
set text item delimiters to toFind
set {L, text item delimiters} to {text items of t, toReplace}
set t to L as text
end repeat
set text item delimiters to tid
return paragraphs of t
end replace_chars
I enclosed the main flow in a run block to help you to understand that this main flow must not embed a handler.
During the cleaning process I assumed that your script is complete, so a lot of instructions appear to be useless.
When I initially checked this, I though it wasn’t working because columns 2 and 3 in the output file were not identical but then I remembered that your handler has reordered the search/replace list, so they won’t line up anymore. But the values swapped out are perfect every time.
Thank you sincerely for your help. You’ve saved my bacon and taught me more about writing code
As I don’t know the length of your lists, I’m wondering if this alternate version is faster.
It split the descriptors items in lists {before, after} before sorting it.
May you explain what you are doing in this part of your code :
set filePath3 to p2h & "Finished_File.txt"
set finaldoc to paragraphs of (read file filePath3)
repeat with i from 1 to finalCNT
try
# Here I'm puzzled. because I see no reason to have the same number of items in the two lists
set end of finaldoc to (item i of uniqueList2 & " " & item i of uniqueList3)
end try
end repeat