linux - استخدام awk لطباعة كل الأعمدة من nth إلى الأخير




gawk (16)

الآن لدي هذا الخط ، وعملت حتى أتيحت لي مساحة بيضاء في الحقل الثاني.

svn status | grep '\!' | gawk '{print $2;}' > removedProjs

هل هناك طريقة لتطبع كل شيء في $ 2 أو أكثر؟ ($ 3 ، $ 4 .. حتى لم يعد لدينا أعمدة؟)

أفترض أنني يجب أن أضيف أنني أفعل ذلك في بيئة Windows مع Cygwin.


أرغب في تمديد الإجابات المقترحة على الوضع حيث يتم تحديد الحقول بواسطة مسافات بيضاء ربما - وهو سبب عدم استخدام OP لسياسة cut أفترضها.

أعرف أن OP سأل عن awk ، ولكن نهج sed ستعمل هنا (مثال مع طباعة الأعمدة من 5 إلى آخر):

  • نقية سيد النهج

    sed -r 's/^\s*(\S+\s+){4}//' somefile
    

    تفسير:

    • يتم استخدام s/// الطريقة القياسية لإجراء الاستبدال
    • ^\s* يتطابق مع أي مسافة بيضاء متتالية في بداية السطر
    • \S+\s+ تعني عمودًا من البيانات (أحرف غير بيضاء متبوعة بمسافات بيضاء)
    • (){4} تعني أن النمط يتكرر 4 مرات.
  • وقطعت

    sed -r 's/^\s+//; s/\s+/\t/g' somefile | cut -f5-
    

    من خلال استبدال المسافات البيضاء المتتالية بعلامة تبويب واحدة فقط ؛

  • tr و cut: tr يمكن أن تستخدم أيضًا لضغط الأحرف المتتالية مع الخيار -s .

    tr -s [:blank:] <somefile | cut -d' ' -f5-
    

أنا شخصيا جربت جميع الإجابات المذكورة أعلاه ، ولكن معظمها كانت معقدة بعض الشيء أو غير صحيحة. أسهل طريقة للقيام بذلك من وجهة نظري هي:

awk -F" " '{ for (i=4; i<=NF; i++) print $i }'
  1. حيث -F "" يعرّف المحدد لاستخدام awk. في حالتي هي المساحة البيضاء ، والتي هي أيضا المحدد الافتراضي ل awk. هذا يعني أنه يمكن تجاهل -F "".

  2. حيث يحدد NF إجمالي عدد الحقول / الأعمدة. لذلك ستبدأ الحلقة من الحقل الرابع حتى آخر حقل / عمود.

  3. حيث يسترد $ N قيمة الحقل Nth. لذلك ، ستطبع $ i طباعة الحقل / العمود الحالي بناءً على عدد الحلقات.


إذا كنت تريد نصًا منسقًا ، فقم بتسلسل الأوامر باستخدام echo واستخدم $ 0 لطباعة الحقل الأخير.

مثال:

for i in {8..11}; do
   s1="$i"
   s2="str$i"
   s3="str with spaces $i"
   echo -n "$s1 $s2" | awk '{printf "|%3d|%6s",$1,$2}'
   echo -en "$s3" | awk '{printf "|%-19s|\n", $0}'
done

مطبوعات:

|  8|  str8|str with spaces 8  |
|  9|  str9|str with spaces 9  |
| 10| str10|str with spaces 10 |
| 11| str11|str with spaces 11 |

إذا كنت لا ترغب في إعادة صياغة جزء الخط الذي لا تختاره ، فإن أفضل حل يمكنني التفكير فيه هو مكتوب في إجابتي في:

كيفية طباعة جميع الأعمدة بعد رقم معين باستخدام awk؟

يقطع ما قبل رقم الحقل المعطى N ، ويطبع كل ما تبقى من الخط ، بما في ذلك رقم الحقل N والحفاظ على التباعد الأصلي (لا يتم إعادة تهيئته). انها لا ماتر إذا ظهرت سلسلة من الحقل أيضا في مكان آخر في السطر.

تحديد وظيفة:

fromField () { 
awk -v m="\x01" -v N="$1" '{$N=m$N; print substr($0,index($0,m)+1)}'
}

واستخدمها على هذا النحو:

$ echo "  bat   bi       iru   lau bost   " | fromField 3
iru   lau bost   
$ echo "  bat   bi       iru   lau bost   " | fromField 2
bi       iru   lau bost 

يحافظ الإخراج على كل شيء ، بما في ذلك مسافات زائدة

في حالة خاصة بك:

svn status | grep '\!' | fromField 2 > removedProjs

إذا كان الملف / الدفق الخاص بك لا يحتوي على أحرف سطر جديد في منتصف الخطوط (يمكنك استخدام فاصل سجل آخر) ، فيمكنك استخدام:

awk -v m="\x0a" -v N="3" '{$N=m$N ;print substr($0, index($0,m)+1)}'

ستفشل الحالة الأولى فقط في الملفات / التدفقات التي تحتوي على رقم char رقم 1 نادر


بيرل:

@m=`ls -ltr dir | grep ^d | awk '{print \$6,\$7,\$8,\$9}'`;
foreach $i (@m)
{
        print "$i\n";

}

تبدو أمثلة Awk معقدة هنا ، هنا هو بناء جملة Bash shell بسيطة:

command | while read -a cols; do echo ${cols[@]:1}; done

حيث يمثل الرقم 1 عمولك رقم n من 0.

مثال

بالنظر إلى محتوى الملف هذا ( in.txt ):

c1
c1 c2
c1 c2 c3
c1 c2 c3 c4
c1 c2 c3 c4 c5

هنا هو الإخراج:

$ while read -a cols; do echo ${cols[@]:1}; done < in.txt 

c2
c2 c3
c2 c3 c4
c2 c3 c4 c5

ستقوم بطباعة جميع الأعمدة باستثناء العمود الأول:

awk '{$1=""; print $0}' somefile

ستقوم بطباعة جميع الأعمدة إلا أولها:

awk '{$1=$2=""; print $0}' somefile

سيعمل هذا إذا كنت تستخدم باش ويمكنك استخدام أكبر عدد ممكن من 'x' كعناصر تريد تجاهلها ويتجاهل مساحات متعددة إذا لم يتم الإفلات منها.

while read x b; do echo "$b"; done < filename

كان هذا يزعجني كثيراً ، جلست وكتبت محلل مواصفات الحقل cut ، تم اختباره مع GNU Awk 3.1.7.

أولاً ، قم بإنشاء برنامج نصي جديد لمكتبة Awk يُسمى pfcut ، على سبيل المثال

sudo nano /usr/share/awk/pfcut

ثم ، الصق في البرنامج النصي أدناه ، وحفظ. بعد ذلك ، هذه هي الطريقة التي يبدو بها الاستخدام:

$ echo "t1 t2 t3 t4 t5 t6 t7" | awk -f pfcut --source '/^/ { pfcut("-4"); }'
t1 t2 t3 t4

$ echo "t1 t2 t3 t4 t5 t6 t7" | awk -f pfcut --source '/^/ { pfcut("2-"); }'
t2 t3 t4 t5 t6 t7

$ echo "t1 t2 t3 t4 t5 t6 t7" | awk -f pfcut --source '/^/ { pfcut("-2,4,6-"); }'
t1 t2 t4 t6 t7

لتجنب كتابة كل ذلك ، أعتقد أن أفضل ما يمكن القيام به (انظر خلاف ذلك تلقائيا تحميل وظيفة المستخدم عند بدء التشغيل مع awk؟ - Unix & Linux Stack Exchange ) إضافة اسم مستعار إلى ~/.bashrc ؛ على سبيل المثال مع:

$ echo "alias awk-pfcut='awk -f pfcut --source'" >> ~/.bashrc
$ source ~/.bashrc     # refresh bash aliases

... عندها يمكنك الاتصال بـ:

$ echo "t1 t2 t3 t4 t5 t6 t7" | awk-pfcut '/^/ { pfcut("-2,4,6-"); }'
t1 t2 t4 t6 t7

في ما يلي مصدر البرنامج النصي pfcut :

# pfcut - print fields like cut
#
# sdaau, GNU GPL
# Nov, 2013

function spfcut(formatstring)
{
  # parse format string
  numsplitscomma = split(formatstring, fsa, ",");
  numspecparts = 0;
  split("", parts); # clear/initialize array (for e.g. `tail` piping into `awk`)
  for(i=1;i<=numsplitscomma;i++) {
    commapart=fsa[i];
    numsplitsminus = split(fsa[i], cpa, "-");
    # assume here a range is always just two parts: "a-b"
    # also assume user has already sorted the ranges
    #print numsplitsminus, cpa[1], cpa[2]; # debug
    if(numsplitsminus==2) {
     if ((cpa[1]) == "") cpa[1] = 1;
     if ((cpa[2]) == "") cpa[2] = NF;
     for(j=cpa[1];j<=cpa[2];j++) {
       parts[numspecparts++] = j;
     }
    } else parts[numspecparts++] = commapart;
  }
  n=asort(parts); outs="";
  for(i=1;i<=n;i++) {
    outs = outs sprintf("%s%s", $parts[i], (i==n)?"":OFS); 
    #print(i, parts[i]); # debug
  }
  return outs;
}

function pfcut(formatstring) {
  print spfcut(formatstring);
}

لم أكن سعيدًا بأي من حلول awk المعروضة هنا لأنني أردت استخراج الأعمدة القليلة الأولى ثم طباعة الباقي ، لذا perl إلى perl بدلاً من ذلك. التوليف التالي يستخرج أول عمودين ، ويعرض الباقي كما هو:

echo -e "a  b  c  d\te\t\tf g" | \
  perl -ne 'my @f = split /\s+/, $_, 3; printf "first: %s second: %s rest: %s", @f;'

الميزة مقارنة مع حل perl من Chris Koknat هو أنه في الحقيقة يتم تقسيم عناصر n الأولى فقط من سلسلة الإدخال؛ بقية السلسلة لا تنقسم على الإطلاق وتبقى سوية تمامًا. يوضح المثال الخاص بي هذا مع مزيج من المسافات وعلامات التبويب.

لتغيير عدد الأعمدة التي يجب استخراجها ، استبدل 3 في المثال بـ n + 1.


هذا ما فضّلته من كل التوصيات:

الطباعة من 6th إلى العمود الأخير.

ls -lthr | awk '{out=$6; for(i=7;i<=NF;i++){out=out" "$i}; print out}'

أو

ls -lthr | awk '{ORS=" "; for(i=6;i<=NF;i++) print $i;print "\n"}'

هل هذا العمل؟

awk '{print substr($0,length($1)+1);}' < file

يترك بعض المسافات البيضاء في الجبهة رغم ذلك.


يمكنك استخدام حلقة for for loop خلال حقول الطباعة $ 2 إلى $ NF (متغير مضمّن يمثل عدد الحقول على السطر).

تعديل: بما أن "print" تلحق سطر جديد ، فستحتاج إلى تخزين النتائج:

awk '{out=""; for(i=2;i<=NF;i++){out=out" "$i}; print out}'

بدلاً من ذلك ، استخدم printf:

awk '{for(i=2;i<=NF;i++){printf "%s ", $i}; printf "\n"}'

awk '{ for(i=3; i<=NF; ++i) printf $i""FS; print "" }'

اقترح lauhub هذا الحل الصحيح وبسيط وسريع here


echo "1 2 3 4 5 6" | awk '{ $NF = ""; print $0}'

هذا واحد يستخدم awk لطباعة جميع باستثناء الحقل الأخير


ls -la | awk '{o=$1" "$3; for (i=5; i<=NF; i++) o=o" "$i; print o }'

من هذا الجواب ليس سيئًا لكن المباعدة الطبيعية انتهت.
يرجى مقارنتها بهذا:

ls -la | cut -d\  -f4-

ثم سترى الفرق.

حتى ls -la | awk '{$1=$2=""; print}' ls -la | awk '{$1=$2=""; print}' ls -la | awk '{$1=$2=""; print}' الذي يستند إلى الإجابة التي تم التصويت عليها بشكل أفضل حتى الآن لا يحافظ على التنسيق.

وبالتالي ، فإنني سأستخدم ما يلي ، كما يسمح أيضًا بالأعمدة الانتقائية الواضحة في البداية:

ls -la | cut -d\  -f1,4-

لاحظ أن كل فضاء للمسافات للأعمدة أيضًا ، لذلك على سبيل المثال في الأسفل ، يكون الأعمدة 1 و 3 فارغين ، و 2 هي INFO و 4 هي:

$ echo " INFO  2014-10-11 10:16:19  main " | cut -d\  -f1,3

$ echo " INFO  2014-10-11 10:16:19  main " | cut -d\  -f2,4
INFO 2014-10-11
$




gawk