Extracting Field 2 of Pipe-Delimited Text

I am trying to copy text between pipelines that gets copied to the clipboard.

A few examples of what ends up in the clipboard.
3| 2| 413
I want to change the clipboard to 2.

115| 4| 495
I want to change the clipboard to 4

122| 3| 016
I want to change the clipboard to 3

122| 1| 269
I want to return 1 to the clipboard.

@ccstone helped me remove everything after the pipeline several years ago.

do shell script "<<<" & quoted form of barNumbers & " sed -En '
  # Remove leading space.
  s!^[[:blank:]]+!!
  # Remove spaces if any, pipe, and all trailing characters.
  s![[:blank:]]*\\|.+!!
  p
'"
set the clipboard to the result

Hey @skillet,

How are you getting the text into the clipboard?

One line at at a time or more than one?

-Chris

Just using command+c

That only partially answers my question.

Oops I am sorry about that I am just doing one at a time. I would never get all those examples at once.

For example a single command+c would yield something like 115| 4| 495

Hey @skillet,

OK – something like this should work for you.

-Chris


RegEx ⇢ Clipboard ⇢ Return Pipe Item 2 ⇢ Remove Whitespace.kmmacros (4.7 KB)

Wow, you completely boggle my mind, I have no idea how you did that. I have tried modifying it in multiple ways to see what results I get. It makes no sense at all how it is doing what it is doing but it is exactly what I was looking for. Thank you very much!

Magic.  :sunglasses:

^.+?\|([^|]+).*
^		==	Anchor at beginning of line
.+		==	One or more characters.
?		==	Non-greedy
\|		==	Literal Pipe (escaped)
(		==	Start capture group
[^|]+	==	Any character NOT Pipe one or more
)		==	End capture group
.*		==	Any character zero or more
\1		==	Return capture group 1

From on High!

Thank you for the explanation that is extremely useful and will be added to my pool of very useful tricks! I will no doubt be needing that in the future. I was going down all sorts of threads on various forums trying to put something together.

Thank you very much kind sir!!

Hey @skillet,

Here’s a very simple AppleScript to break up delimited text.

Try part 1 of the script in the Script Editor.app after copying your text to the clipboard.

Your text example:

3| 2| 413
# Part 1 of script.
set clipboardText to the clipboard
set AppleScript's text item delimiters to {"|"}
set foundItem to text item 2 of clipboardText
# Part 1 of script written more tersely.
set AppleScript's text item delimiters to {"|"}
set foundItem to text item 2 of (get the clipboard)
# Part 1 of script written to get ALL delimited text items.
set AppleScript's text item delimiters to {"|"}
set foundItem to text items of (get the clipboard)

Anyone who uses AppleScript at all should have a basic understanding of text items. They’re very simple to use, very fast, and quite useful.

Part 2 of the script below uses somewhat more specialized knowledge to filter out whitespace from the answer.

----------------------------------------------------------------
# Auth: Christopher Stone
# dCre: 2018/04/21 15:27
# dMod: 2018/04/21 15:27 
# Appl: AppleScript
# Task: Find text item 2 delimited by the pipe character.
# Libs: None
# Osax: None
# Tags: @Applescript, @Script, @Find, @Text, @Item, @Delimited, @Pipe, @Character
----------------------------------------------------------------
# Simple use of text items (part 1):
----------------------------------------------------------------

set clipboardText to the clipboard

set AppleScript's text item delimiters to {"|"}
set foundItem to text item 2 of clipboardText

----------------------------------------------------------------
# More complicated use of list filter form to remove whitespace (part 2):
----------------------------------------------------------------

set foundItem to characters of foundItem
repeat with i in foundItem
   if contents of i = " " then
      set contents of i to 0
   end if
end repeat

set AppleScript's text item delimiters to {""}
set foundItem to (text of foundItem) as text

----------------------------------------------------------------

-Chris

1 Like

If the data after the first pipe is always a series of one or more digits, then you could simplify with:

^.*?\|\h*(\d+).*
image

No need to trim.

This also:

  • Allows for null (nothing) before the first pipe.
  • Allows for any amount of horizontal whitespace (including none) after the first pipe.

For details, paste the RegEx pattern and example data into Regex101.com

1 Like

Fantastic, thank you both very much!

Hey @skillet,

Here’s another way of doing the job with AppleScript and the Keyboard Maestro Engine’s search/replace command.

----------------------------------------------------------------
# Auth: Christopher Stone
# dCre: 2018/04/21 16:00
# dMod: 2018/04/21 16:07
# Appl: Keyboard Maestro Engine
# Task: Extract item 2 of pipe-delimited text.
# Libs: None
# Osax: None
# Tags: @Applescript, @Script, @Keyboard_Maestro_Engine, @Extract, @Pipe-delimited, @Text
----------------------------------------------------------------

set the clipboard to "

3| 2| 413

  " -- simulate data already being on the clipboard - add some junky whitespace for testing.

set dataStr to the clipboard

# Split text on the pipe character and any surrounding horizontal whitespace.
set foundText to kmReplace("\\h*\\|\\h*", "\\n", dataStr, true, true, true)

# Remove any other existing horizontal whitespace for good measure.
set foundText to kmReplace("\\h+", "", foundText, true, true, true)

# Remove any leading or trailing vertical whitespace for good measure.
set foundText to kmReplace("\\A\\s+|\\s+\\Z", "", foundText, true, true, true)

set foundText to paragraph 2 of foundText

----------------------------------------------------------------
--» HANDLERS
----------------------------------------------------------------
on kmReplace(findPattern, replacePattern, dataStr, regExBool, caseBool, tokensBool)
  tell application "Keyboard Maestro Engine"
     set foundDataList to search dataStr for findPattern replace replacePattern ¬
        regex regExBool case sensitive caseBool process tokens tokensBool
  end tell
end kmReplace
----------------------------------------------------------------

Note that I’m teaching techniques here and not just specific targeted regex.

If I was doing this job for myself I’d use the Satimage AppleScript Extension and make the job really simple:

----------------------------------------------------------------
# The Satimage.osax MUST be installed for this to work!
----------------------------------------------------------------
set the clipboard to "

3| 2| 413

   " -- simulate data already being on the clipboard - add some junky whitespace for testing.

set foundText to item 2 of (find text "\\d+" in (get the clipboard) with regexp, all occurrences and string result)

This is really simple in that I’m finding all contiguous digits, and the result is an AppleScript list.

So all I have to do then is pick the second item in the list.

-Chris

Hey Guys,

Here’s another one using the Keyboard Maestro Engine without using a handler.

----------------------------------------------------------------
# Auth: Christopher Stone
# dCre: 2018/04/21 16:00
# dMod: 2018/04/21 19:46
# Appl: Keyboard Maestro Engine
# Task: Extract item 2 of pipe-delimited text.
# Libs: None
# Osax: None
# Tags: @Applescript, @Script, @Keyboard_Maestro_Engine, @Extract, @Pipe-delimited, @Text, @RegEx
----------------------------------------------------------------

set the clipboard to "

3| 2| 413

   " -- simulate data already being on the clipboard - add some junky whitespace for testing.

set dataStr to the clipboard

tell application "Keyboard Maestro Engine"
   set dataStr to search dataStr for "(?s)^.+?\\|[^\\d]*(\\d+).*" replace "$1" with regex without case sensitive and process tokens
end tell

----------------------------------------------------------------

The regular expression is more like JM’s, although it allows for the possibility of vertical whitespace and uses [^\\d]* (any character other than digit zero or more) instead of the horizontal whitespace token.

-Chris

Hey Guys,

Just for fun here's a macro using Awk to do all the work.

It was pesky to figure out, but in the end the syntax isn't that bad.

-Chris


Extract Field 2 of a Pipe-Delimted String v1.00.kmmacros (5.7 KB)

Holy smokes Chris you’re a macro coding wizard! It will take me a few weeks to process all you guys have given me. Astonishing there are so many ways to pull this off!

115| 4| 495
I want to change the clipboard to 4

The following solution doesn't need KM:
After the input text is copied to the clipboard, enter this directly at the Terminal Command line:

pbpaste | awk -F"|" '{print $2}' | pbcopy

The clipboard will contain the item after the first pipe.
Changing to -F"," will use commas as the field separators
Changing $2 to $1, $3 etc. will select that numbered field

If KM is more convenient because of its many trigger options (hotkey, palette, …):
you can add the above one-line command to a "Execute Shell Script" action.

Yep.

See post #15:wink:

-Chris

Agree it’s almost a duplicate. Composed while traveling and uploaded without spotting your answer.