Anda dapat menggunakan awk ini:
awk -v s='2,4' 'BEGIN{split(s, a, ","); for (i in a) b[a[i]]} NR in b' file
two
four
Melalui skrip terpisah lines.sh
:
#!/bin/bash
awk -v s="$1" 'BEGIN{split(s, a, ","); for (i in a) b[a[i]]} NR in b' "$2"
Kemudian berikan izin eksekusi:
chmod +x lines.sh
Dan menyebutnya sebagai:
./lines.sh '2,4' 'test.txt'
Coba sed
:
sed -n '2p; 4p' inputFile
-n
memberi tahu sed
untuk menekan keluaran, tetapi untuk baris 2
dan 4
, p
(cetak) perintah digunakan untuk mencetak baris-baris ini.
Anda juga dapat menggunakan rentang, mis.:
sed -n '2,4p' inputFile
Dua versi Bash murni. Karena Anda sedang mencari solusi umum dan dapat digunakan kembali, sebaiknya Anda berusaha sedikit untuk itu. (Juga, lihat bagian terakhir).
Versi 1
Skrip ini memasukkan seluruh stdin ke dalam array (menggunakan mapfile
, jadi agak efisien) lalu mencetak baris yang ditentukan pada argumennya. Rentang valid, mis.,
1-4 # for lines 1, 2, 3 and 4
3- # for everything from line 3 till the end of the file
Anda dapat memisahkannya dengan spasi atau koma. Baris-baris dicetak persis sesuai dengan urutan argumen yang diberikan:
lines 1 1,2,4,1-3,4- 1
akan mencetak baris 1 dua kali, lalu baris 2, lalu baris 4, lalu baris 1, 2 dan 3, lalu semuanya dari baris 4 hingga akhir, dan terakhir, baris 1 lagi.
Ini dia:
#!/bin/bash
lines=()
# Slurp stdin in array
mapfile -O1 -t lines
# Arguments:
IFS=', ' read -ra args <<< "$*"
for arg in "${args[@]}"; do
if [[ $arg = +([[:digit:]]) ]]; then
arg=$arg-$arg
fi
if [[ $arg =~ ([[:digit:]]+)-([[:digit:]]*) ]]; then
((from=10#${BASH_REMATCH[1]}))
((to=10#${BASH_REMATCH[2]:-$((${#lines[@]}))}))
((from==0)) && from=1
((to>=${#lines[@]})) && to=${#lines[@]}
((from<=to)) || printf >&2 'Argument %d-%d: lines not in increasing order' "$from" "$to"
for((i=from;i<=to;++i)); do
printf '%s\n' "${lines[i]}"
done
else
printf >&2 "Error in argument \`%s'.\n" "$arg"
fi
done
- Pro:Keren banget.
- Con:Perlu membaca seluruh aliran ke dalam memori. Tidak cocok untuk streaming tanpa batas.
Versi 2
Versi ini mengatasi masalah aliran tak terbatas sebelumnya. Namun Anda akan kehilangan kemampuan untuk mengulang dan menyusun ulang baris.
Hal yang sama, rentang diperbolehkan:
lines 1 1,4-6 9-
akan mencetak baris 1, 4, 5, 6, 9 dan semuanya sampai akhir. Jika rangkaian baris dibatasi, keluar segera setelah baris terakhir dibaca.
#!/bin/bash
lines=()
tillend=0
maxline=0
# Process arguments
IFS=', ' read -ra args <<< "[email protected]"
for arg in "${args[@]}"; do
if [[ $arg = +([[:digit:]]) ]]; then
arg=$arg-$arg
fi
if [[ $arg =~ ([[:digit:]]+)-([[:digit:]]*) ]]; then
((from=10#${BASH_REMATCH[1]}))
((from==0)) && from=1
((tillend && from>=tillend)) && continue
if [[ -z ${BASH_REMATCH[2]} ]]; then
tillend=$from
continue
fi
((to=10#${BASH_REMATCH[2]}))
if ((from>to)); then
printf >&2 "Invalid lines order: %s\n" "$arg"
exit 1
fi
((maxline<to)) && maxline=$to
for ((i=from;i<=to;++i)); do
lines[i]=1
done
else
printf >&2 "Invalid argument \`%s'\n" "$arg"
exit 1
fi
done
# If nothing to read, exit
((tillend==0 && ${#lines[@]}==0)) && exit
# Now read stdin
linenb=0
while IFS= read -r line; do
((++linenb))
((tillend==0 && maxline && linenb>maxline)) && exit
if [[ ${lines[linenb]} ]] || ((tillend && linenb>=tillend)); then
printf '%s\n' "$line"
fi
done
- Pro:Sangat keren dan tidak membaca aliran penuh di memori.
- Kontra:Tidak dapat mengulang atau menyusun ulang baris sebagai Versi 1. Kecepatan bukanlah poin terkuatnya.
Pemikiran lebih lanjut
Jika Anda benar-benar menginginkan skrip umum yang luar biasa yang melakukan apa yang dilakukan Versi 1 dan Versi 2, dan lebih banyak lagi, Anda pasti harus mempertimbangkan untuk menggunakan bahasa lain, misalnya, Perl:Anda akan mendapatkan banyak (dalam kecepatan tertentu)! Anda akan dapat memiliki opsi bagus yang akan melakukan banyak hal yang jauh lebih keren. Ini mungkin bermanfaat dalam jangka panjang, karena Anda menginginkan skrip yang umum dan dapat digunakan kembali. Anda bahkan mungkin memiliki skrip yang membaca email!
Penafian. Saya belum memeriksa skrip ini secara menyeluruh... jadi waspadalah terhadap bug!