Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/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"
Advertisement