String Template Processor
A flexible, composable string transformation CLI tool and Rust library. string_pipeline
lets you chain operations like split, join, slice, replace, case conversion, trim, and more, using a concise template syntax. It is ideal for quick text manipulation, scripting, and data extraction.
Table of Contents
Features
- Composable operations: Chain multiple string operations in a single template.
- Split and join: Extract and reassemble parts of strings.
- Slice and range: Select sub-strings or sub-lists by index or range.
- Regex replace: sed-like regex search and replace.
- Filtering: Filter lists with regex patterns using
filter
andfilter_not
. - Case conversion: Uppercase and lowercase.
- Trim and strip: Remove whitespace, custom characters, ansi sequences.
- Append and prepend: Add text before or after.
- Smart escaping: Contextual pipe handling - no escaping needed in most cases.
- Flexible indices: Python-like negative indices in ranges and slices with Rust-like syntax.
- Stdin support: Read input from stdin when no input argument is provided.
- Debug mode: Add
!
after{
to print debug info for each operation. - Robust error handling: Helpful error messages for invalid templates or arguments.
- Tested: Comprehensive test suite.
Crate
Find the crate on crates.io:
[]
= "0.7.0"
Installation
CLI
Clone and build:
Or run directly with Cargo:
Library
Add to your Cargo.toml
as shown above.
Usage
As a CLI
# With input argument
# With stdin input
|
Examples:
# Get the second item in a comma-separated list
# Output: b
# Replace all spaces with underscores and uppercase
# Output: FOO_BAR_BAZ
# Trim, split, and append
# Output: a!,b!,c!,d!,e!
# Using stdin for processing file content
|
As a Library
use process;
Template Syntax
Templates are enclosed in {}
and consist of a chain of operations separated by |
.
Arguments to operations are separated by :
.
Syntax Reference
- Template:
{ [!] operation_list? }
- Add
!
after{
to enable debug mode.
- Add
- Operation List:
operation ('|' operation)*
- Operation:
split:<sep>:<range>
- Shorthand for split:
{index}
(e.g.{1}
, equivalent to{split: :1}
){range}
(e.g.{1..3}
, equivalent to{split: :1..3}
)
- Shorthand for split:
join:<sep>
substring:<range>
replace:s/<pattern>/<replacement>/<flags>
upper
lower
trim
strip:<chars>
append:<suffix>
prepend:<prefix>
strip_ansi
filter:<regex_pattern>
filter_not:<regex_pattern>
slice:<range>
Supported Operations
Operation | Syntax | Description |
---|---|---|
Split | split:<sep>:<range> |
Split by separator, select by index/range |
Join | join:<sep> |
Join a list with separator |
Substring | slice:<range> |
Extract substrings |
Replace | replace:s/<pattern>/<replacement>/<flags> |
Regex replace (sed-like) |
Uppercase | upper |
Convert to uppercase |
Lowercase | lower |
Convert to lowercase |
Trim | trim |
Trim whitespace |
Strip | strip:<chars> |
Trim custom characters |
Append | append:<suffix> |
Append text |
Prepend | prepend:<prefix> |
Prepend text |
StripAnsi | strip_ansi |
Removes ansi escape sequences |
Filter | filter:<regex_pattern> |
Keep only items matching regex pattern |
FilterNot | filter_not:<regex_pattern> |
Remove items matching regex pattern |
Slice | filter_not:<regex_pattern> |
Select elements from a list |
Range Specifications
Ranges use Rust-like syntax and support negative indices like Python:
Range | Description | Example |
---|---|---|
N |
Single index | {split:,:1} → second element |
N..M |
Exclusive range | {split:,:1..3} → elements 1,2 |
N..=M |
Inclusive range | {split:,:1..=3} → elements 1,2,3 |
N.. |
From N to end | {split:,:2..} → from 2nd to end |
..N |
From start to N | {split:,:..3} → first 3 elements |
..=N |
From start to N inclusive | {split:,:..=2} → first 3 elements |
.. |
All elements | {split:,:..) → all elements |
Negative indices count from the end:
-1
= last element-2
= second to last element-3..
= last 3 elements
Escaping
The parser intelligently handles pipe characters (|
) based on context:
Pipes are automatically allowed in:
- Split separators:
{split:|:..}
(splits on pipe) - Regex patterns:
{filter:\.(txt|md|log)}
(alternation) - Sed replacements:
{replace:s/test/a|b/}
(pipe in replacement)
Manual escaping needed for:
- Other arguments: Use
\|
for literal pipes in join, append, prepend, etc. - Special characters: Use
\:
for literal colons,\\
for backslashes - Escape sequences: Use
\n
,\t
,\r
for newline, tab, carriage return
Enable Debug Mode
- Add
!
after{
to enable debug output for each operation:- Example:
{!split:,:..|upper|join:-}
- Example:
Examples
Basic
# Get the last item
# Output: c
# Get a range of items
# Output: b,c,d
# Replace 'foo' with 'bar' globally
# Output: bar bar
# Chain operations: uppercase, then append
# Output: HELLO!
# Prepend with a colon (escaped)
# Output: :foobar
Advanced
# Complex chaining: split, select range, join, replace, uppercase
# Output: X-B
# Slice string characters
# Output: ell
# Split, trim each item, then prepend
|
# Output: item_a,item_b,item_c
# Strip custom characters
# Output: hello
Real-World
# Process CSV-like data
|
# Output: age,city
# Format file paths
|
# Output: file.txt
# Extract file extension
|
# Output: PDF
# Process log entries with timestamps
|
# Output: error failed to connect
# Clean colored git output
|
# Process ls colored output
|
# Clean grep colored output
|
# Chain with other operations
| \
# Output: RED | GREEN
# Process log files with ANSI codes
|
Shorthand
# Get the second word (space-separated)
# Output: bar
# Get a range of words
# Output: bar baz
Debug Mode
# Print debug info for each operation
# DEBUG: Initial value: Str("a,b,c")
# DEBUG: Applying operation 1: Split { sep: ",", range: Range(None, None, false) }
# DEBUG: Result: List with 3 items:
# DEBUG: [0]: "a"
# DEBUG: [1]: "b"
# DEBUG: [2]: "c"
# DEBUG: ---
# DEBUG: Applying operation 2: Upper
# DEBUG: Result: List with 3 items:
# DEBUG: [0]: "A"
# DEBUG: [1]: "B"
# DEBUG: [2]: "C"
# DEBUG: ---
# DEBUG: Applying operation 3: Join { sep: "-" }
# DEBUG: Result: String("A-B-C")
# DEBUG: ---
# A-B-C
Testing
Run the test suite:
Contributing
Contributions and suggestions are welcome! Please open issues or pull requests on GitHub.
License
This project is licensed under the MIT License. See LICENSE for details.
Enjoy fast, composable string transformations!