#!/bin/bash
print_usage() {
echo "Usage:"
echo " collect [-o] [-m] [-i] range file"
echo " Examples:"
echo " collect 1,3 file.txt # Copy lines to clipboard"
echo " collect -o 1,3 file.txt # Print lines to stdout"
echo " collect -m 1,3:5,7:9,9 file.txt # Multiple ranges, separated by ':'"
echo " collect -i 1,3 file.txt # Inverse selection (all except lines 1-3)"
exit 1
}
validate_range() {
local range=$1
local file=$2
local total_lines=$(wc -l < "$file")
if ! [[ $range =~ ^[0-9]+(,[0-9]+)?$ ]]; then
echo "Error: Invalid range format '$range'. Expected format: n or n,m"
return 1
fi
IFS=',' read -r start end <<< "$range"
if [ -z "$end" ]; then
end=$start
fi
if [ "$start" -gt "$end" ]; then
echo "Error: Invalid range '$range'. Start line must be less than or equal to end line."
return 1
fi
if [ "$start" -eq 0 ] || [ "$end" -gt "$total_lines" ]; then
echo "Error: Range '$range' is out of bounds. File has $total_lines lines."
return 1
fi
return 0
}
process_range() {
local range=$1
local file=$2
local inverse=$3
local total_lines=$(wc -l < "$file")
if [ "$inverse" = true ]; then
IFS=',' read -r start end <<< "$range"
if [ -z "$end" ]; then
end=$start
fi
if [ "$start" -gt 1 ]; then
sed -n "1,$((start-1))p" "$file"
fi
if [ "$end" -lt "$total_lines" ]; then
sed -n "$((end+1)),$((total_lines))p" "$file"
fi
else
sed -n "${range}p" "$file"
fi
}
if [ "$#" -lt 2 ]; then
print_usage
fi
output_mode=false
multi_range=false
inverse_mode=false
while getopts "omi" opt; do
case ${opt} in
o )
output_mode=true
;;
m )
multi_range=true
;;
i )
inverse_mode=true
;;
\? )
print_usage
;;
esac
done
shift $((OPTIND -1))
if [ "$#" -ne 2 ]; then
print_usage
fi
ranges=$1
file=$2
if [ ! -f "$file" ]; then
echo "Error: File '$file' does not exist."
exit 1
fi
if [ "$multi_range" = true ]; then
IFS=':' read -ra RANGE_ARRAY <<< "$ranges"
for range in "${RANGE_ARRAY[@]}"; do
if ! validate_range "$range" "$file"; then
exit 1
fi
done
else
if ! validate_range "$ranges" "$file"; then
exit 1
fi
fi
if [ "$output_mode" = false ]; then
if ! command -v xclip &> /dev/null; then
echo "Error: xclip could not be found. Please install xclip."
exit 1
fi
fi
if [ "$inverse_mode" = true ] && [ "$multi_range" = true ]; then
echo "Error: Inverse selection (-i) cannot be used with multiple ranges (-m)"
exit 1
fi
temp_file=$(mktemp)
if [ "$multi_range" = true ]; then
for range in "${RANGE_ARRAY[@]}"; do
process_range "$range" "$file" false >> "$temp_file"
done
else
process_range "$ranges" "$file" "$inverse_mode" >> "$temp_file"
fi
if [ "$output_mode" = true ]; then
cat "$temp_file"
else
cat "$temp_file" | xclip -selection clipboard
if [ "$inverse_mode" = true ]; then
echo "All lines except $ranges from file '$file' have been copied to the clipboard."
else
echo "Lines $ranges from file '$file' have been copied to the clipboard."
fi
fi
rm "$temp_file"
Comments
0 B
|👍
/👎
0 B
|👍
/👎
0 B
|👍
/👎
0 B
|👍
/👎
0 B
|👍
/👎
0 B
|👍
/👎
0 B
|👍
/👎
0 B
|👍
/👎
0 B
|👍
/👎
0 B
|0 👍
/0 👎