Thứ Ba, 27 tháng 11, 2012

Kiểm tra các website cùng Server hoặc cùng IP

Nếu như bạn muốn biết trên server đặt web site của mình có những website nào thì bạn có thể kiểm tra thông qua website sau:

http://www.dedicatedornot.com

Sau khi điền địa chỉ IP hoặc tên miền website của bạn thì nó hiển thị danh sách các website nằm chung server với bạn.


Vì sao phải kiểm tra xem có những site nào chung server với bạn? Theo Manlivo đc biết  thì 1 server chỉ có đủ tài nguyên để cung cấp dịch vụ cho 1 số lượng website nhất định. Nếu như  server cung cấp dịch vụ share hosting mà đặt quá nhiều website thì sẽ làm tốn tài nguyên và rất có thể gây ra lỗi trên server. Điển hình như  lỗi connect đến dịch vụ mysql. Vì vậy biết được bao nhiêu site cùng server với chúng ta sẽ làm giảm rủi ro tối website cũng như  có thể biết trước và chọn một đặt website tại 1 server khác.

Chú ý tuy là nhiều website nhỏ thì cũng chưa chắc ảnh ưởng nhiều bằng việc chung server với 1 website có lượt truy cập cao.

Thứ Hai, 26 tháng 11, 2012

Tăng tốc cho ứng dụng ASP.NET MVC với Output Caching

Trong bài hướng dẫn này, bạn sẽ học cách tăng tốc độ ứng dụng ASP.NET MVC bằng cách sử dụng output caching. Bạn sẽ học cách cache kết quả trả về từ controller action do đó nội dung đó sẽ không cần phải tạo lại mỗi khi người dùng gọi đến action đó.

 

Trong bài hướng dẫn này, bạn sẽ học cách tăng tốc độ ứng dụng ASP.NET MVC bằng cách sử dụng output caching. Bạn sẽ học cách cache kết quả trả về từ controller action do đó nội dung đó sẽ không cần phải tạo lại mỗi khi người dùng gọi đến action đó.

Ví dụ như ứng dụng ASP.NET MVC của bạn hiển thị danh sách các dòng dữ liệu lấy từ Database ra một View có tên là Index, mỗi khi người dùng gọi controller action trả về view Index, dữ liệu trên sẽ được trả về từ CSDL bằng cách gọi một câu truy vấn đến CSDL.

Nhưng nếu như bạn sử dụng ouput cache thì bạn sẽ tránh được việc phải thực hiện câu truy vấn CSDL mỗi khi action đó được gọi. View sẽ được lấy lên từ cache (bộ nhớ tạm của ứng dụng) thay vì phải gọi action tạo ra dữ liệu và trả kết quả về. Caching giúp cho bạn tránh phải bắt server thực thi lặp đi lặp lại một hành động.

Hữu hiệu Output Caching

Bạn có thể cho phép output caching bằng cách thêm thuộc tính [OutputCache] cho controller action hoặc cho cả controller. Ở Mã minh họa 1, action có tên là Index sẽ được cache trong mỗi mười giây.

 

Mã minh họa 1 – Controllers\HomeController.cs

 


using System.Web.Mvc;    namespace MvcApplication1.Controllers  {      [HandleError]      public class HomeController : Controller      {          [OutputCache(Duration=10, VaryByParam="none")]          public ActionResult Index()          {              return View();          }        }  }     

 

 

Trong mã minh họa 1, nội dung trả về của action Index() được cache trong 10 giây. Nếu bạn thích, bạn có thể quy định thời gian cache (cache duration) dài hơn. Ví dụ, nếu bạn muốn cache một action trong một ngày, bạn có thể quy định thời lượng cach trong 86400 giây ( 60 giây * 60 phút * 24 giờ).

Tuy nhiên, không có gì đảm bảo nội dung sẽ được cache trong thời lượng bạn quy định. Khi tài nguyên bộ nhớ thấp, nội dung cache sẽ bị xóa tự động.

Controller Home trong mã minh họa 1 trả về view Index trong mã minh họa 2. View này chả có nội dung gì đặc biệt, nó chỉ hiển thị thời gian hiện tại (xem Hình 1).

Mã minh họa 2 – Views\Home\Index.aspx

 


<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Index.aspx.cs" Inherits="MvcApplication1.Views.Home.Index" %>  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">  <html xmlns="http://www.w3.org/1999/xhtml" >  <head runat="server">      <title>Index</title>  </head>  <body>      <div>            The current time is: <%= DateTime.Now.ToString("T") %>                  </div>  </body>  </html>     

 

 

Hình 1 – view Index đã bị cache

Nếu như bạn gọi action Index() nhiều lần thì bạn sẽ thấy thời gian hiển trị trên view Index sẽ không thay đổi trong vòng 10 giây bởi vì kết quả này đã bị cache.

Bạn cũng phải lưu ý rằng, view này sẽ bị cache và kết quả sẽ được lấy từ cache để cung cấp cho bất cứ ai thăm ứng dụng của bạn. Điều này có nghĩa rằng, thời gian mà web server phải sử dụng để phục vụ view Index cho người dùng được giảm đi đáng kể.

Đừng dụng chỉ thị <%@ OuputCache %> trong view. Chỉ thị này dành riêng cho ứng dụng Web Forms và không nên được dùng trong ứng dụng ASP.NET MVC.

Các nội dung được cache ở đâu?

Theo mặc định, khi bạn sử dụng thuộc tính [OutputCache], nội dung được cache ở ba nơi: ở web server, bất kỳ proxy server nào và web browser. Bạn có thể quy định nơi nào được cache bằng cách thay đổi thuộc tính Location của [OuputCache].

Bạn có thể quy định các giá trị sau cho thuộc tính Location:

· Any

· Client

· Downstream

· Server

· None

· ServerAndClient

Giá trị mặc định của thuộc tính Location có giá trị là Any. Tuy nhiên, có những tình huống mà bạn chỉ muốn cache ở trình duyệt hoặc ở server mà thôi. Ví dụ, nếu bạn muốn cache thông tin được tùy biến cho người dùng, do đó bạn không nên cache thông tin ở server.

Ví dụ, controller ở mã minh họa 3 có một action GetName() trả về tên người dùng hiện tại. Giả sử có người tên "Minh" là người đầu tiên triệu gọi action này, thì những người dùng sau khi triệu gọi trong vòng 1 phút sẽ được trả về kết quả là "Hi Minh" vì nội dung đã được cache ở server.

Mã minh họa 3 – Controllers\BadUserController.cs

 


using System.Web.Mvc;  using System.Web.UI;    namespace MvcApplication1.Controllers  {      public class BadUserController : Controller      {          [OutputCache(Duration = 3600, VaryByParam = "none")]          public string GetName()          {              return "Hi " + User.Identity.Name;          }      }  }     

 

 

Bạn không nên cache nội dung mang tính cá nhân ở server. Thay vào đó, bạn nên cache chúng ở cache của trình duyệt để tăng tốc độ cho ứng dung. Nếu bạn cache nội dung ở trình duyệt và khi người dùng triệu gọi một action nhiều lần thì nội dung sẽ được trả về từ cache của trình duyệt thay vì được lấy từ server.

Ở mã minh họa 4, action GetName() đã được điều chỉnh để chỉ cache ở trình duyệt, và nhờ vậy, những người dùng khác nhau sẽ nhận được kết quả trả về là chính tên của họ chứ không phải tên của một người nào khác.

Mã minh họa 4 – Controllers\UserController.cs

 


using System.Web.Mvc;  using System.Web.UI;    namespace MvcApplication1.Controllers  {      public class UserController : Controller      {          [OutputCache(Duration=3600, VaryByParam="none", Location=OutputCacheLocation.Client, NoStore=true)]          public string GetName()          {              return "Hi " + User.Identity.Name;          }      }  }     

 

 

Lưu ý rằng thuộc tính [OuputCache] ở Mã minh họa 4 có bao gồm thuộc tính NoStore. Thuộc tính NoStore với giá trị true có tác dụng yêu cầu proxy servers và trình duyệt không lưu bản sao của nội dung được cache.

Cache action theo tham số

Trong một số trường hợp, bạn sẽ muốn có các phiên bản cache khác nhau cho cùng một nội dung. Ví như khi bạn tạo một trang dạng master/detail. Trang master hiển thị danh sách các tiêu đề phim, khi bạn click chuột vào tên một phim thì bạn sẽ nhận được nội dung giới thiệu chi tiết về phim đó.

Nếu bạn cache nội dung trang chi tiết, thì chi tiết của phim được hiển thị chung nội dung phim được cache bất kể bạn click vào tên phim nào. Và nội dung phim mà người dùng đầu tiên xem sẽ được cache cho những người xem sau.

Bạn có thể khắc phục lỗi này bằng cách sử dụng thuộc tính VaryByParam của [OutputCache]. Thuộc tính này giúp bạn tạo các phiên bản cache riêng biệt tùy theo giá trị của tham số và người dùng truy vấn một action.

Ví dụ, controller ở Mã minh họa 5 có hai action có tên là Master() và Details(). Action Master() trả về danh sách tên các phim và Details() trả về nội dung chi tiết của mỗi phim.

Mã minh họa 5 – Controllers\MoviesController.cs

 


using System.Linq;  using System.Web.Mvc;  using MvcApplication1.Models;    namespace MvcApplication1.Controllers  {      public class MoviesController : Controller      {          private MovieDataContext _dataContext;            public MoviesController()          {              _dataContext = new MovieDataContext();          }            [OutputCache(Duration=int.MaxValue, VaryByParam="none")]          public ActionResult Master()          {              ViewData.Model = (from m in _dataContext.Movies                                 select m).ToList();              return View();          }            [OutputCache(Duration = int.MaxValue, VaryByParam = "id")]          public ActionResult Details(int id)          {              ViewData.Model = _dataContext.Movies.SingleOrDefault(m => m.Id == id);              return View();          }          }  }     

 

 

Action Master() có đính kèm thuộc tính VaryByParam với giá trị là "none". Khi Master() được gọi, nội dung được cache duy nhất của view Master() sẽ được trả về (xem hình 2).

Hình 2 – /Movies/Master 

Hình 3 – /Movies/Details

Action Details() đính kèm thuộc tính VaryByParam với giá trị là "Id".  Và do đó, khi giá trị của tham số Id được truyền vào action thì sẽ có một phiên bản cache được sinh ra và lưu lại.

Ngoài ra bạn có thể gán các giá trị sau cho thuộc tính VaryByParam:

* = Tạo ra các phiên bản cache khác nhau đối với tham số truyền lên khác nhau

none = Chỉ duy trì phiên bản cache chung cho mọi giá trị tham số

Danh sách các tham số (phân tách bằng dấu ;) = Tạo các phiên bản cache khác nhau tùy theo giá trị của các tham số mà bạn quy định.

Tạo Cache Profile

Nhược điểm của việc quy định các tham số trực tiếp trên thuộc tính [OuputCache] đó là bạn không thể thay đổi nó khi đã biên dịch thành tập tin dll. Và vì vậy Microsoft cho phép quy định các tham số của thuộc tính [OuputCache] tại tận tin cấu hình web.config. Cách này mang lại cho hai lợi ích chính, thứ nhất là cho phép bạn áp dụng một cache profile cho nhiều action khác nhau. Lợi ích thứ hai, quan trọng không kém, cho phép bạn tùy chỉnh các tham số cấu hình mà không cần phải biên dịch lại dự án, mọi thay đối ở tập tin web.config sẽ được xác định tự động và có hiệu lực ngay sau đó.

Ví dụ, mục <caching> trong tập tin web.config ở Mã minh họa 6 định nghĩa một cache profile có tên là Cache1Hour. Mục <caching> được định nghĩa bên trong mục <system.web> của tập tin web.config.

Mã minh họa 6 – Caching section ở web.config

 


<caching>  <outputCacheSettings>      <outputCacheProfiles>          <add name="Cache1Hour" duration="3600" varyByParam="none"/>      </outputCacheProfiles>  </outputCacheSettings>  </caching>     

 

 

Controller trong Mã minh họa 7 minh họa cho bạn cách áp dụng cấu hình Cache1Hour cho action với thuộc tính [OuputCache].

Mã minh họa 7 – Controllers\ProfileController.cs

 


using System;  using System.Web.Mvc;    namespace MvcApplication1.Controllers  {      public class ProfileController : Controller      {          [OutputCache(CacheProfile="Cache1Hour")]          public string Index()          {              return DateTime.Now.ToString("T");          }      }  }     

 

 

Nếu bạn triệu gọi action Index() cho Mã minh họa 7 thì action sẽ được cache trong 1 giờ.

Tổng kết

Ouput caching giúp cho bạn có thể dễ dàng tăng tốc các ứng dụng ASP.NET MVC. Ở bài viết này, bạn được học cách sử dụng thuộc tính [OuputCache] để cache kết quả trả về bởi các action. Bạn cũng đã được học cách điều chỉnh các tham số của thuộc tính [OutputCache] như là Duration và VaryByParam để điều chỉnh cách thức cache nội dung trả về. Và cuối cùng bạn học được cách quy đính cấu hình cache trong tập tin web.config của ứng dụng.


Cảm ơn tác giả :  tumivn - Link nguồn : d.jou.vn/Article/Tang-toc-cho-ung-dung-ASPNET-MVC-voi-Output-Caching/13

Thứ Bảy, 24 tháng 11, 2012

Tổng quan ASP.NET MVC Routing

Trong hướng dẫn này, bạn sẽ được giới thiệu với một tính năng quan trọng của mọi ứng dụng ASP.NET MVC ASP.NET gọi là định tuyến. The ASP.NET Routing module có trách nhiệm lập bản đồ các yêu cầu trình duyệt gửi tới các action cụ thể Controller MVC. Đến cuối này, bạn sẽ hiểu thế nào là con đường tiêu chuẩn bảng yêu cầu bản đồ để Controller Action.

Sử dụng mặc định Route Table
Khi bạn tạo một mới ứng dụng ASP.NET MVC, ứng dụng đã được cấu hình để sử dụng ASP.NET Routing. ASP.NET định tuyến được thiết lập tại hai nơi.

Trước tiên, ASP.NET định tuyến được kích hoạt trong tập tin cấu hình ứng dụng của bạn Web (web.config file). Có bốn phần trong file cấu hình có liên quan đến việc định tuyến: phần system.web.httpModules, phần system.web.httpHandlers, phần system.webserver.modules, và phần system.webserver.handlers. Hãy cẩn thận không để xóa những phần này vì không có các phần định tuyến sẽ không còn làm việc.

Thứ hai, và quan trọng hơn, một bảng tuyến đường được tạo ra trong file Global.asax của ứng dụng. File Global.asax là một file đặc biệt có chứa bộ xử lý sự kiện cho ASP.NET sự kiện vòng đời ứng dụng. Bảng lộ trình được tạo ra trong sự kiện Đơn Bắt đầu.

Các tập tin trong 1 danh mục chứa các file Global.asax mặc định cho một ứng dụng ASP.NET MVC.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;

namespace MvcApplication1
{
// Note: For instructions on enabling IIS6 or IIS7 classic mode,

public class MvcApplication : System.Web.HttpApplication
{
       public static void RegisterRoutes(RouteCollection routes)
      {
             routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
             routes.MapRoute(
                   "Default", // Route name
                   "{controller}/{action}/{id}", // URL with parameters
                   new { controller = "Home", action = "Index", id = "" } // Parameter defaults
             );
       }
      protected void Application_Start()
     {
              RegisterRoutes(RouteTable.Routes);
      }
}
}

Khi một ứng dụng MVC đầu tiên bắt đầu, các method Application_Start() được gọi. method này, đến lượt nó, gọi RegisterRoutes(). Các method RegisterRoutes() tạo route table.

Mặc định route table có một con đường duy nhất (có tên mặc định). Các bản đồ mặc định phân tuyến đoạn đầu tiên của một URL để một tên điều khiển, phân khúc thứ hai của một URL cho một Controller Action, và đoạn thứ ba đến một tham số có tên là id.

Hãy tưởng tượng rằng bạn nhập URL sau đây vào thanh địa chỉ trình duyệt web của bạn: /Home/Index/3

Các mặc định bản đồ tuyến đường URL để các thông số sau:

controller = Home
action = Index
id = 3

Khi bạn yêu cầu URL /Home/Index/3, các code sau đây được thực thi: HomeController.Index(3)

Các tuyến đường mặc định bao gồm giá trị mặc định cho tất cả ba thông số. Nếu bạn không cung cấp một bộ điều khiển, sau đó điều khiển các thông số mặc định để các chủ giá trị. Nếu bạn không cung cấp một hành động, các tham số hành động mặc định theo Chỉ số giá trị. Cuối cùng, nếu bạn không cung cấp một id, các thông số mặc định id cho một chuỗi rỗng.

Hãy xem xét một số ví dụ về cách các tuyến đường mặc định bản đồ các URL để hành động điều khiển. Hãy tưởng tượng rằng bạn nhập URL sau đây vào thanh địa chỉ trình duyệt của bạn: /Home

Bởi vì các thông số mặc định mặc định đường đi, cách nhập URL này sẽ gây ra Index() phương thức của lớp HomeController trong danh mục 2 để được gọi.

using System.Web.Mvc;
namespace MvcApplication1.Controllers
{
        [HandleError]
        public class HomeController : Controller
       {
              public ActionResult Index(string id)
             {
                     return View();
             }
       }
}

Trong danh mục 2, class HomeController bao gồm một method đặt tên là Index() chấp nhận một tham số đơn Mã đặt tên. URL /Home làm cho method Index() có thể được gọi với một chuỗi rỗng như giá trị của tham số ID.

Bởi vì các cách mà framework MVC invokes Controller action, URL /Home cũng phù hợp với method Index() của lớp HomeController trong danh mục 3.

using System.Web.Mvc;
namespace MvcApplication1.Controllers
{
        [HandleError]
        public class HomeController : Controller
       {
                public ActionResult Index()
                {
                        return View();
                }
        }
}

Method Index() trong danh mục 3 không chấp nhận bất kỳ thông số. URL /Home này sẽ được gọi là method Index(). URL /Home/Index/3 cũng invokes phương pháp này(Mã là bỏ qua).

URL /Home phù hợp với method Index() của lớp HomeController trong danh mục 4.

using System.Web.Mvc;
namespace MvcApplication1.Controllers
{
         [HandleError]
         public class HomeController : Controller
         {
                 public ActionResult Index(int? id)
                {
                          return View();
                }
         }
}

Trong 4 danh mục, method Index() có một tham số Integer. Bởi vì tham số này là một tham số nullable (có thể có giá trị Null), Index() có thể được gọi là lỗi.

Cuối cùng, method Index() trong danh mục 5 với URL /Home gây ra một ngoại lệ từ các tham số ID không phải là một tham số nullable. Nếu bạn cố gắng gọi method Index() sau đó bạn nhận được lỗi hiển thị trong hình 1.

using System.Web.Mvc;
namespace MvcApplication1.Controllers
{
         [HandleError]
         public class HomeController : Controller
         {
                public ActionResult Index(int id)
               {
                       return View();
               }
         }
}

Thứ Sáu, 23 tháng 11, 2012

[Android] Cài đặt Android SDK Plugin cho Eclipse 3.5 trên windows


Chào các bạn, sau đây mình sẽ hướng dẫn chi tiết cho các bạn cách cài đặt hay đúng hơn là tích hợp Android Plugin vào Eclipse để giúp chúng ta dễ dàng tạo và quản lí Android Project.

Để thực hành thì trước tiên chúng ta cần phải làm những bước cơ bản sau:

1. Tải Eclipse 3.5 (GALILEO) tại địa chỉ sau: http://www.eclipse.org/downloads/download.php?file=/eclipse/downloads/drops/R-3.5-200906111540/eclipse-SDK-3.5-win32.zip&mirror_id=999&url=http://d2u376ub0heus3.cloudfront.net/galileo/eclipse-SDK-3.5-win32.zip

hoặc http://d2u376ub0heus3.cloudfront.net/galileo/eclipse-SDK-3.5-win32.zip

2. Giải nén tệp vừa cài đặt vào thư mục mà bạn muốn đặt Eclipse, ví dụ: C:\Eclipse3.5 (nếu bạn dùng nhiều phiên bản eclipse khác nhau thì nên đặt tên theo kiểu này) hoặc C:\Eclipses (nếu bạn chỉ dùng duy nhất 1 phiên bản eclipse) – Ổ đĩa không bắt buộc là ổ C.

***Sau khi đã hoàn tất 2 bước trên chúng ta sẽ tiến hành cài đặt Android plugin theo các bước sau:
Bước 1: Khởi động Eclipse

Bước 2: Chọn Help/Install New Update

Bước 3: Chọn nút Add trên hộp thoại để hiện của sổ Add site
Bạn hãy làm theo những gì trên hình dưới đây
Lưu ý: hộp Name có thể đặt tên theo ý của bạn còn hộp Localtion thì bắt buộc phải là https://dl-ssl.google.com/android/eclipse/

[Bạn hãy chọn OK để để tiếp tục quá trình cài đặt]

Bước 4: Đợi eclipse lấy thông số plugin từ địa chỉ trên

Bước 5: Bạn check vào Developer Tools sau đó chọn Next để tiếp tục

và đợi eclipse gom các yêu cầu hệ thống và các thư viện liên quan sau đó sẽ tải chúng về nếu máy của bạn chưa có sẵn

Bước 6: Chọn Next theo hình sau

Bước 7: chấp nhận thỏa thuận sử dụng sau đó chọn Finish

Bước 8: Ngồi đợi quá trình cài đặt tự động

Bước cuối cùng là Restart lại Eclipse hoặc chọn Apply để Eclipse cập nhật những thông số cho Android.
Lưu ý: bạn nên restart lại.

Phù! vậy là chúng ta đã hoàn thành việc tích hợp Android vào Eclipse nhé.

Chúc các bạn thành công!

p/s: mình sẽ post tiếp bài sử dụng thiết lập Android SDK cho eclipse và tạo ứng dụng Android trong Eclipse. Mời các bạn đón đọc và cho ý kiến .
reflink: -http://diendan.vietandroid.com/su-dung-google-android-sdk/114-cai-dat-android-sdk-plugin-cho-eclipse-3-5-tren-windows.html

Cài đặt chuẩn bị lập trình Android


I.Hướng dẫn cài đặt Android với Eclipse:
Thực chất anh Giáp đã viết một bài có nội dung tương tự, nhưng do Goolge thay đổi phương thức tải Android SDK nên mình quyết định viết lại, gộp luôn vào topic hướng dẫn sử dụng Eclipse.

1.Download Android SDK:

Android SDK thực chất là tập hợp các công cụ và thư viện để phát triển các ứng dụng trên nền tảng hệ điều hành Android.

B1: Vào trang http://developer.android.com/sdk/index.html để tải Android SDK Starter. Tùy thuộc vào hệ điều hành mà bạn chọn bản Mac, Linux hay Window. Ở đây mình chọn tải bản cho Window.

B2: Giải nén file zip bạn vừa tải về. Chạy SDK Setup.exe. Bạn có thể gặp thông báo lỗi Fetching https://dl-sl… Failed to fetch… Close thông báo này lại. Tiếp theo cửa sổ Choose Packages to Install xuất hiện. Nếu cửa sổ này trống rỗng -> Cancel.
-> Quay về cửa sổ Android SDK and AVD manager -> Chọn Setting, đánh dấu vào ô Force https://...
-> Chọn Available Packages

B3: Đánh dấu các Packages bạn muốn tải: Documents chính là phần Javadoc mô tả hoạt động của các phương thức và các lớp (phần này chắc chắn không thể thiếu rồi), Sample là các đoạn code mẫu, SDK Platform ứng với các phiên bản hệ điều hành (2.2 – API level 8, 2.1 – API level 7,…), và Google API để phát triển các phần mềm liên quan đến dịch vụ của Google (như Google Map nếu bạn muốn lập trình liên quan đến GPS).
Các bạn có thể tải hết nếu thích, còn muốn tối ưu thì có thể đánh dấu như mình (lưu ý USB drivers chỉ dành cho người sử dụng Windows và muốn phát triển ứng dụng test bằng điện thoại thật).
-> Install Selected
-> Install
-> Cửa sổ Install hiện ra
-> Ngồi chờ (>_<)

2.Tích hợp Android SDK vào Eclipse:

B1: Tải Eclipse nếu bạn chưa có. Mọi người có thể phân vân không biết tải bản nào cho phù hợp, nhưng theo ý kiến của mình thì có thể dùng 1 trong 2 bản sau: Eclipse for Java Developers, hoặc Eclipse for Java and Report Developers (mình dùng bản sau).

B2: Khởi chạy Eclipse, vào Help -> Install new softwares.
Chọn Add, gõ vào ô Name tên bạn muốn và Location gõ vào địa chỉ để tải về ADT:
HTML Code:

https://dl-ssl.google.com/android/eclipse/

hoặc
HTML Code:

http://dl-ssl.google.com/android/eclipse/

nếu https không hoạt động. Ngoài ra bạn cũng có thể tải thẳng ADT về máy theo linkhttp://dl.google.com/android/ADT-0.9.7.zip (bản mới nhất 0.9.7 ứng với Android 2.2), chọn Archive và browse tới file này (lưu ý không giải nén)
-> OK
-> Check vào phần dưới ô Name (sẽ hiện ra dòng Developer Tools).



B3: Next, next, Accept, next,…Finish (như Install mọi chương trình bình thường).

B4: Eclipse -> Windows -> Preferences -> Android
Nhấn nút Browse và chỉnh đường dẫn tới thư mục của Android SDK bạn tải lúc trước.
-> Apply
-> OK



3.Android Virtual Device (Emulator):

AVD là máy ảo cho developer phát triển ứng dụng. Để tạo 1 AVD bạn vào Windows -> Android SDK and AVD Manager -> Virtual Devices chọn New.
-> Cửa sổ Create new AVD hiện ra, bạn điền thông tin cho AVD bạn muốn:

Name: Tùy ý (nhưng chỉ được sử dụng các ký tự “a-z”, “A-Z”, “.-_”, nghĩa là cả khoảng trắng cũng ko đc).

Target: Chọn phiên bản hệ điều hành bạn muốn (thường mình tạo một Android 1.6 và một Android 2.2 để test).

SD Card: gõ vào Size SD card ảo cho AVD, hoặc chỉnh tới file đã có sẵn. Nhiều AVD có thể dùng chung 1 Sdcard (chỉ cần tạo lần đầu, các lần sau chỉnh đường dẫn tới file đó).

Skin: có thể để Default (HVGA) hoặc chọn kích cỡ màn hình bạn muốn. Chỉ cần quan tâm tới 3 option: HVGA (phân giải 320-480 như G1, G2, i5700…), QVGA (240-320 như HTC Wildfire…), WVGA854 (480-854 như Milestone, NexusOne…)
-> Create AVD.

II.Một số chức năng cần biết khi lập trình Android với Eclipse:Những điều mình nêu ra dưới đây đều là cơ bản, có thể các pro đã biết hết rồi, nhưng như mình đã nói, bài này là dành cho newbie với hi vọng gia tăng kiến thức cơ bản cùng giảm thời gian tìm kiếm cho các bạn.

1.Debug cho ứng dụng Android:

Nhiều người chuyển từ J2SE hoặc J2ME sang Android sẽ ngạc nhiên vì câu lệnh debug kinh điểnSystem.out.println() không còn in ra trên cửa sổ Console nữa. Google đã thay thế nó bằng Logcat, một cửa sổ ghi lại toàn bộ hoạt động của hệ điều hành. Để mở Logcat, trước tiên các bạn chọn Window -> Open Perspective -> Debug. Nếu ko thấy option Debug thì chọn Other và tìm Debug trong cửa sổ mới hiện ra. Sau đó chọn tab Debug mới xuất hiện ở góc trên bên phải của Eclipse (xem hình). Theo kinh nghiệm của mình thì tốt nhất là Maximize Logcat ra luôn cho dễ quan sát.

Cảm nhận ngày xưa khi mới sử dụng Logcat là rối và khó dùng. Nhưng càng về sau mình càng quen và thấy nó tiện hơn Console nhiều, vì Console chỉ đưa ra thông báo do chúng ta gọi, còn Logcat thì đưa cả luôn những thông báo của hệ điều hành, giúp chúng ta nắm được hệ điều hành đang làm gì, gọi đến cái gì, khởi chạy những gì…

2.File Explorer của Android:

File Explorer là một chức năng hữu ích Google đưa vào giúp chúng ta quản lý file trong sd card và cả file system data (chỉ quản lý được của emulator, không thể truy nhập system data của thiết bị thật). FE giúp bạn dễ dàng đưa file vào / lấy file ra trong sdcard ảo của emulator, xóa cơ sở dữ liệu của chương trình để khởi tạo lại (only emulator)…

Mở FE bằng cách vào Window -> Show View -> Others -> Android -> File Explorer. Mình để FE trong cửa sổ Debug cho tiện quản lý.

3.Device của Android:

Device cũng là một chức năng hữu ích nữa trong Android giúp bạn quản lý thiết bị ảo cũng như thật của mình. Mở Device bằng cách vào Window -> Show View -> Device hoặc vào Window -> Show View -> Others -> Android -> Device.

Chức năng mình thường sử dụng nhất của device là Screen Capture, cực kỳ tiện để lấy ảnh minh họa làm thuyết trình hoặc giới thiệu trên Google Market.

[Android] App Inventor: Viết ứng dụng cho Android thật dễ dàng


Trong vài tuần nữa, Google sẽ cho người dùng tải về chương trình thiết kế ứng dụng có tên App Inventor. Với chương trình này, bạn không cần phải có bất cứ kiến thức nào về lập trình cũng có thể tạo các ra phần mềm cho Android từ cơ bản đến nâng cao. Với giao diện trực quan, dễ hiểu, cho phép truy cập đến các chức năng của điện thoại kể cả GPS, đây sẽ là công cụ giúp cho bộ sưu tập ứng dụng của Android ngày càng dồi dào và phong phú.

Điểm nổi bật của App Inventor là nó cho phép bạn vừa thiết kế ứng dụng vừa xài thử ứng dụng đó trực tiếp trên chiếc điện thoại Android đang được kết nối với máy tính. Tất cả các công đoạn viết phần mềm đều thông qua giao diện đồ họa trực quan theo kiểu WYSIWYG (What you see is what you get) mà không cần bạn phải đụng tới một đoạn mã nào. Các chỉ dẫn trên màn hình đủ dễ hiểu để bạn có thể tiến hành viết phần mềm ngay mà không nhất thiết phải xem qua các bản hướng dẫn sử dụng.

Tuy có cách dùng đơn giản nhưng App Inventor khá “hào phóng” khi cho phép bạn truy xuất đến các chức năng thường dùng của điện thoại như chức năng tự động nhắn tin, xác định vị trí hiện tại qua GPS và kể cả giao tiếp với các ứng dụng trên nền web như Amazon, Facebook hay Twitter.

Lịch sử phát triển các phiên bản Android

Android hiện là nền tảng di động rất phổ biến và được nhiều hãng sản xuất phần cứng sử dụng. Dù Android Inc. được thành lập vào năm 2003 song phải tới khi nó thuộc về tay của Google (năm 2005) thì tên tuổi của Android mới bắt đầu được biết đến. Năm 2008, thiết bị đầu tiên chạy Android là HTC Dream được giới thiệu và nhiều phiên bản Android cùng nhiều thiết bị khác được ra mắt sau đó. Hiện tại Android đang có hai phiên bản dành cho smartphone (Android 2.3) và dành cho tablet (Android 3.0) nhưng tới cuối năm nay thì cả hai sẽ được gộp lại thành một (Ice Cream Sandwich). Dưới đây là các cột mốc phát triển của nền tảng mở Android, từ khi thành lập tới khi bản Android 3.2 xuất hiện.


[Android] Phần 1: Giới thiệu Android


Understanding Android” là cách mà ta tiếp cận lập trình Android và thấu hiểu kiến trúc hệ thống của nó. Bạn có thể không cần hiểu rõ cấu trúc của một hệ điều hành nhưng bạn vẫn có thể lập trình một ứng dụng trên HDH đó, đây là điều mà nhà sản xuất muốn khi release SDK với một framework có sẵn của họ. Như bạn biết điều này cũng có mặt tốt và xấu. Framework là một tầng cao cấp dành cho lập trình viên, nó đều có giới hạn của nó, bạn có thể chỉ có thể lập trình những ứng dụng phổ biến nhưng không nên tiến tới những ứng dụng cao cấp đi sâu vào hệ thống của HDH. Theo cách của mình, trước khi bắt đầu học Android, chúng ta nên nghiên cứu qua bản thân hệ điều hành Android, chúng ta không cần phải hiểu rõ nó như thể nào, mục đích quan trọng nhất của chúng ta là có cái nhìn chung và toàn diện nhất về Android.

Android là gì:
Android là một hệ điều hành mã nguồn mở, chủ yếu dành cho các thiết bị di động. Nhà phát triển có thể đem mã nguồn mở này về, modify bằng cách thêm code của họ hoặc dùngGoogle’s Java và build ra một hệ điều hành Android riêng cho mình. Đây cũng là cách mà HTC, Motorola, LG, Samsung … đang làm để đưa Android lên thiết bị của họ.
Một số tính năng của HDH Android: Handset layouts, Storage, Connectivity, Messaging, Web Browser, Java Virtual Machine, Media Support, Additional Hardware Support …
Android Platform:

Bao gồm hệ điều hành Android đầy đủ tính năng, các ứng dụng và các tầng trung gian để developer có thể mở rộng, modify hoặc thêm vào component của họ.

android live wallpapers copy Part I: Understanding Android

Picture 4 copy Part I: Understanding Android

Có 4 tầng cơ bản trong HDH Android: Application Framework, Android Runtime, Native Libraries, Linux Kernel … Mỗi tầng làm việc đều nhờ sự giúp đỡ của tầng bên dưới.
Tầng Linux Kernel:

Đây là nhân của hệ điều hành Android, mọi xử lý của hệ thống đều phải thông qua tầng này.
Linux Kernel cung cấp các trình điều khiển thiết bị phần cứng (driver) như: camera, USB, Wifi, Bluetooth, Display, Power Management …

Android dựa trên Linux phiên bản 2.6 lựa chọn các tính năng cốt lõi như bảo mật, quản lý bộ nhớ, quản lý tiến trình, mạng stack, và các trình điều khiển phần cứng. Kernel hoạt động như một lớp trừu tượng giữa phần cứng và phần mềm còn lại của hệ thống.

Picture 6 copy Part I: Understanding Android
Tầng Native Libraries:

Picture 8 copy Part I: Understanding Android

* System C library – có nguồn gốc từ hệ thống thư viện chuẩn C (libc), điều chỉnh các thiết bị nhúng trên Linux.

* Media Libraries – mở rộng từ PacketVideo’s OpenCORE; thư viện hỗ trợ playback và recording của nhiều định dạng video và image phổ biến: MPEG4, H.264, MP3, AAC, AMR, JPG, and PNG

* Surface Manager – quản lý việc hiển thị và kết hợp đồ họa 2D và 3D.

* LibWebCore – Android dùng lại webkit engine cho việc render trình duyệt mặc định của HDH Android browser và cho dạng web nhúng (như HTML nhúng)

* SGL – 2D engine

* 3D libraries – Thư viện 3D dựa trên OpenGL ES 1.0 API, có nâng cấp tăng tốc “hardware 3D acceleration”

* FreeType – render bitmap và vector font

* SQLite – quản lý database của ứng dụng
Tầng Runtime:

Picture 1 copy2 Part I: Understanding Android

Mỗi ứng dụng Android chạy trên một proccess riêng của Dalvik VM (máy ảo). Dalvik được viết để chạy nhiều máy ảo cùng một lúc một cách hiệu quả trên cùng một thiết bị.

Máy ảo Dalvik thực thi các file mang định dạng .dex (Dalvik Excutable), định dạng này là định dạng đã được tối ưu hóa để chỉ chiếm một vùng nhớ vừa đủ xài và nhỏ nhất có thể. VM chạy các class (đã được compile trước đó bởi 1trình biên dịch ngôn ngữ Java), sở dĩ VM chạy đc các class này là nhờ chương trình DX tool đã convert các class sang định dang .dex
Tầng Application Framework:

Picture 2 copy2 Part I: Understanding Android

Đây là tầng mà Google xây dựng cho các developer để phát triển các ứng dụng của họ trên Android, chỉ bằng cách gọi các API có sẵn mà Google đã viết để sử dụng các tính năng của phần cứng mà không cần hiểu cấu trúc bên dưới.
Bằng cách cung cấp một nền tảng phát triển mở, Android cho các nhà phát triển khả năng xây dựng các ứng dụng cực kỳ phong phú và sáng tạo. Nhà phát triển được tự do tận dụng các thiết bị phần cứng, thông tin địa điểm truy cập, các dịch vụ chạy nền, thiết lập hệ thống báo thức, thêm các thông báo để các thanh trạng thái, và nhiều, nhiều hơn nữa.

Tất cả các ứng dụng thường gồm một bộ các dịch vụ và hệ thống cơ bản sau:

*View UI dùng để xây dựng layout của ứng dụng bao gồm: list view, text field, button, dialog, form …
* Content Providers cho phép các ứng dụng có thể truy cập dữ liệu từ các ứng dụng khác (như ứng dụng của ta có thể lấy thông tin Contacts của điện thoại Android), hoặc để chia sẻ dữ liệu của riêng ứng dụng.
* Resource Manager cung cấp cách thức truy cập đến non-code resources như các asset, graphic, image, music, video …
* Notification Manager cho phép tất cả các ứng dụng hiển thị thông báo của mình trên hệ điều hành
* Activity Manager quản lý vòng đời của các ứng dụng.

Ở góc nhìn của người dùng ta có thêm tầng application (là ứng dụng do ta viết), sau đây là sơ đồ tổng quát:

system architecture Part I: Understanding Android

Quy Trình khởi động của HDH Android

Picture 3 copy2 Part I: Understanding Android

Bootloader của thiết bị sẽ load kernel và tiến hành khởi động 3 tiến trình của HDH Android: daemons, Zygote, Runtime:

-Zygote, là một tiến trình để khởi động máy ảo Java .
-Daemons quản lý phần cứng cấp thấp như USB, radio …
-Runtine proccess khởi động “Service Manager”.

Sau đó Runtime proccess yêu cầu Zygote khởi động một máy ảo mới Dalik VM cho việc khởi động “System Server”. Cả 2 tiến trình đầu tiên được khởi động sau đó là graphic va audio outputs (Audio & Surface Manager).

Kế tiếp là các tiến trình khác” Telephony, Bluetooth, Activity Manager, Package Manager …

Tất cả các tiến trình chạy ngầm được tạo ra đều phải đc đăng ký và chịu sự quản lý của Service Manager.

Note: Như vậy sau một đóng thông tin trên, bạn sẽ khó mà hấp thụ hết, nhưng đùng lo chỉ khi nào bắt tay vào viết một ứng dụng thì bạn mới bắt đầu sẽ hiểu rõ chúng có công dụng gì. Cuối cùng bạn chỉ cần ghi nhớ một số thông tin sau:

-Android là một mã nguồn mở của Google dựa trên kernel Linux 2.6 . Các nhà sản xuất phải đem mã nguồn này về và custom , rồi build ra HDH Android trên thiết bi của mình.

-Application Framework là phần mà ta sẽ nghiên cứu chủ yếu khi viết một ứng dụng Android và chúng ta không cần phải hiểu cặn kẽ các tầng khác (có thể quên nó :D)

Reference from http://developer.android.com/guide/basics/what-is-android.html

Cơ bản về biểu thức chính quy ( tiếp theo)

Biểu thức so mẫu (pattern) dùng để mô tả 1 cách tổng quát 1 đối tượng (chuỗi) trong PHP, ví dụ:
preg_replace('/[^a-z0-9]+/i',",$str);
–> hàm này l loại bỏ tất cả các ký tự không phải là chữ (a-z và A-Z) hoặc số (0-9) ra khỏi chuỗi $str

Biểu thức so mẫu dùng rất hiệu quả và nhanh chóng, tuy nhiên theo TG biết thì cũng không nhiều người biết sử dụng cái này(nhất là ở nơi không có trường lớp đào tạo cơ bản về PHP như VN chúng ta) còn số người biết,hiểu rõ thì không training lại nên đã ít nay càng ít người biết sử dụng biểu thức so mẫu. Trong bài này TG chỉ giới thiệu 1 số kiến thức cơ bản và 1 vài ví dụ để dễ hiểu, hy vọng là giúp ít cho anh em.
Cấu trúc: như ví dụ trên thì /[^a-z0-9]+/i là 1 biểu thức so mẫu,

- giới hạn trong cặp dấu /<so mẫu>/x hoặc #<so mẫu>#x
x có thể là 1 hoặc nhiều ký tự để mô tả dữ liệu được lấy và cũng có thể không có trong biểu thức so mẫu. Một số giá trị có thể có của  x:
i: không phân biệt chữ hoa, chữ thường
s: bao gồm cả các ký tự xuống dòng
+ Ngoài còn có 1 số giá trị khác như: S,U,… nhưng ít được sử dụng

Ta lấy ví dụ cho dễ hình dung:
preg_replace('/[^a-z0-9]/',",'phpBASIC$')
-> php
preg_replace('/[^a-z0-9]/i',",'phpBASIC$')
-> phpBASIC
Ý nghĩa của các ký tự trong biểu thức so mẫu:

\ loại bỏ các ký tự đặc biệt của pattern
/(phpbasic)/ : chuỗi phpbasic
/\(phpbasic\)/ : chuỗi (phpbasic)
^ ký tự bắt đầu
/^php(.*)/ : những chuỗi bắt đầu bằng chữ php
$ ký tự kết thúc
/(.*)basic$/ : những chuỗi kết thúc bằng chữ basic
. bất kỳ ký tự nào trừ ký tự xuông dòng
/(.*)/ : tất cả các ký tự nằm trên 1 dòng
[ và ] bắt đầu và kết thúc 1 lớp ký tự
/[a-z]/ : tất cả các ký tự a-z
chú ý trong 1 lớp:
^ phủ định:
/[^a-z]/ : những ký tự không phải là a-z
-  1 khoảng:
/[a-d]/ : bao gồm a,b,c,d
| hoặc
/a|b/ : ký tự a hoặc b
( và ) bắt đầu và kết thúc 1 so  mẫu con
/^a(c|d)b/ : chuỗi có dạng acb hoặc acd
? có hoặc không
/ab?c/ : chuỗi có dạng abc hoặc ac
* : 0 hoặc nhiều hơn ký tự
/a*/ : <null>, a, aa, aaa,………….
+ : có ít nhất 1
/a+/ : a,aa,aaa,……………
{ và } bắt đầu và kết thúc min/max ký tự
/a{1,3}/ :  a,aa,aaa

Các ký tự đặc biệt khác:

\n hoặc \r : ký tự xuông dòng
\t : ký tự tab
\d : bất kỳ ký tự số nào
\D : bất kỳ ký tự nào mà không phải là số
\s : bất kỳ ký tự khoảng trắng
\S : bất kỳ ký không phải là khoảng trắng
\w : bất kỳ từ nào
\W : không phải là từ

Biểu thức chính quy(Regular Expressions)

Regular Expressions là gì?
Regular Expressions (Regex) dịch ra tiếng Việt là Biểu thức chính quy. Khái niệm này nằm trong 1 mớ lý thuyết vô cùng đồ sộ và hầm hố . Nhưng ko nên lo lắng, ta có thể hiểu nôm na Regex là 1 cái mẫu (pattern) dùng để mô tả 1 lớp ký tự nào đó.

VD: lazydog là 1 regex. Nó là 1 mẫu đơn giản nhất vì nó so khớp (match) với đoạn text lazydog. 1 match là 1 đoạn text so khớp với mẫu.

VD phức tạp hơn 1 chút: \b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}\b Đây là mẫu mô tả 1 địa chỉ email. Mẫu này có thể dc dùng để tìm 1 địa chỉ email trong 1 đoạn văn bản, hoặc kiểm tra xem 1 chuỗi có phải là địa chỉ email hợp lệ hay ko.

Regex có thể dc sử dụng với bất kỳ dữ liệu nào mà ta có thể truy cập, thông qua ứng dụng hoặc ngôn ngữ lập trình. Có thể kể đến 1 số ứng dụng xử lý văn bản hỗ trợ regex: PowerGREP, EditPad Pro, RegexBuddy,…

Regular Expression Engines

Regex engine là 1 bộ phận của phần mềm, chuyên để xử lý regex (so khớp mẫu với 1 chuỗi nào đó). Có nhiều regex engine và chúng ko hoàn toàn tương thích với nhau. Cú pháp regex (flavor) của mỗi engine cũng có sự khác nhau. Loạt bài này sẽ tập trung vào cú pháp regex dc sử dụng trong Perl 5, vì nó phổ biến nhất. Rất nhiều engine regex khác giống với engine sử dụng trong Perl 5: engine nguồn mở PCRE (sử dụng trong rất nhiều ngôn ngữ lập trình, như PHP, cái ta cần đây hehe ), thư viện regex .NET,…

OK vậy là ta đã hiểu sơ qua regex là cái gì, giờ để tấn công vào cái địa ngục này, ta cần có vũ khí. Có thể sử dụng 1 số ứng dụng xử lý text ở trên để thực hành các biểu thức regex, hoặc ko thì ta tự tạo lấy 1 cái thô sơ bằng PHP.

Trong PHP, ta có thể sử dụng biểu thức regex thông qua các hàm regex. PHP cung cấp 3 nhóm hàm regex, tên của chúng dc bắt đầu bởi: ereg, mb_ereg và preg. 2 loại đầu sử dụng engine POSIX Extended, còn preg sử dụng engine PCRE (Perl-Compatible). Vậy thì vũ khí của ta đơn giản chỉ là đoạn mã PHP sau:

<?php
$string = 'chuỗi cần áp dụng biểu thức regex';
$pattern = '/biểu thức regex/';
preg_match($pattern, $string, $match);
echo $match[0];
?>

Nó sẽ hiện lên màn hình kết quả so khớp biểu thức regex với chuỗi mà ta áp dụng regex vào. Như thấy ở trên, ta dùng nhóm hàm preg vì nó sử dụng engine PCRE rất giống với engine của Perl, loại engine có cú pháp mà ta đang thảo luận ở đây. Trong loạt bài này, ta sẽ qui ước màu sắc như trong đoạn mã trên: red cho biểu thức regex, green cho chuỗi áp dụng regex, và blue cho kết quả so khớp.

Ký tự thông thường và ký tự đặc biệt

Ký tự thông thường (Literal Characters)

Regex cơ bản nhất chính là biểu thức bao gồm 1 ký tự thông thường, VD: a. Nó sẽ so khớp với thực thể đầu tiên của ký tự đó trong chuỗi. VD nếu có chuỗi: LazyDog is a boy, nó sẽ so khớp với ký tự a sau ký tự L. Regex này cũng có thể so khớp với ký tự a thứ 2 nếu ta điều khiển regex engine tiếp tục tìm kiếm sau khi đã so khớp dc 1 lần.

Cũng như vậy, regex dog sẽ so khớp với dog trong chuỗi LazyDog is not a dog. Regex này bao gồm 1 sêri 3 ký tự thông thường. Engine sẽ hiểu biểu thức này là: tìm d, theo sau bởi o, theo sau bởi g.

Chú ý rằng regex engine mặc định phân biệt chữ hoa và chữ thường. Dog ko so khớp với dog.

Ký tự đặc biệt (Special Characters)

Vì ta cần làm nhiều công việc phức tạp hơn là tìm kiếm 1 đoạn văn bản, cho nên phải trưng dụng 1 vài ký tự để làm những nhiệm vụ đặc biệt. Trong cú pháp regex dc thảo luận ở đây, có 11 ký tự mang ý nghĩa đặc biệt: [ \ ^ $ . | ? * + ( ). Chúng dc gọi là các metacharacter.

Nếu cần dùng các ký tự này với ý nghĩa thông thường, ta phải giải phóng nó bằng \. VD nếu cần so khớp 1+1=2, thì regex đúng sẽ là 1\+1=2. Chú ý rằng 1+1=2 cũng là regex đúng, nên sẽ ko báo lỗi, nhưng nó sẽ ko cho ta kết quả như mong muốn. Regex 1+1=2 sẽ so khớp với 111=2 trong chuỗi 123+111=234, vì dấu + ở đây mang ý nghĩa đặc biệt.

Nếu ta quên ko giải phóng ký tự đặc biệt ở những chỗ nó ko dc phép đứng thì sẽ gặp lỗi. VD: +1

Hầu hết các loại cú pháp regex đều coi { như 1 ký tự thông thường, trừ khi nó là 1 phần của toán tử nhắc lại (repetition operator), VD: {1, 3}. Vì vậy ta ko cần giải phóng ký tự này.

Ta chỉ dùng \ để giải phóng các ký tự đặc biệt, còn các ký tự khác thì ko nên, vì \ cũng là 1 ký tự đặc biệt. \ khi kết hợp với 1 ký tự thông thường sẽ có ý nghĩa đặc biệt, VD: \d sẽ so khớp với 1 chữ số từ 0 - 9.

Tất cả các loại cú pháp regex đều cho phép giải phóng 1 ký tự đặc biệt bằng \. Rất nhiều cú pháp khác còn hỗ trợ kiểu giải phóng \Q... \E. Tất cả các ký tự nằm trong cặp \Q và \E sẽ dc coi như ký tự thông thường. VD: \Q*\d+*\E sẽ so khớp với đoạn văn bản *\d+* . Kiểu cú pháp này dc hỗ trợ bởi JGsoft engine, Perl, PCRE, ...

Ký tự đặc biệt và ngôn ngữ lập trình

Khác với trong ngôn ngữ lập trình, trong regex, ký tự ' và " ko phải là ký tự đặc biệt. Vì vậy, ko cần phải giải phóng nó.

Trong mã nguồn của 1 chương trình, cần luôn ghi nhớ những ký tự nào dc ngôn ngữ lập trình xử lý đặc biệt. Bởi vì những ký tự này sẽ dc trình biên dịch xử lý trước khi dc engine regex xử lý. VD: regex 1\+1=2 phải dc viết thành 1\\+1=2 trong mã nguồn C++. Trình biên dịch C++ sẽ chuyển \\ thành \ trong chuỗi trên, sau đó nó mới dc chuyển đến regex engine. VD khác: đế so khớpc:\temp, cần dùng regex c:\\temp (vì \t trong regex mang ý nghĩa đặc biệt). Và trong mã nguồn C++, regex này cần dc viết là c:\\\\temp. Đúng là địa ngục . Ko bit trong PHP của chúng ta thì thế nào đây hic  :'(.

Ký tự ko in được

Có thể dùng các tổ hợp ký tự đặc biệt để đặt các ký tự ko in dc vào regex.

\t cho ký tự tab (ASCII 0x09)
\r cho carriage return (0x0D)
\n cho line feed (0x0A).
\a (bell, 0x07)
\e (escape, 0x1B)
\f (form feed, 0x0C)
\v (vertical tab, 0x0B).

Chú ý rằng Windows text files sử dụng \r\n để kết thúc dòng, còn UNIX text files sử dụng \n.

Có thể dùng cách này để viết bất kỳ ký tự nào nếu biết mã 16 ASCII của ký tự đó trong bảng mã đang dùng. VD trong bảng mã Latin-1, ký tự copyright có mã 0xA9. Vì thế để tìm ký tự này, ta dùng \xA9.

Hầu hết các loại cú pháp regex còn cho phép sử dụng tổ hợp \cA đến \cZ (c cố định, theo sau bởi 1 chữ cái hoa từ A - Z) để biểu thị ký tự điều khiển. VD \cA biểu thị Control+A. \cM biểu thị Control+M, hay carriage return, giống như \r.

Nếu regex engine hỗ trợ Unicode, ta sử dụng \uFFFF thay cho \xFF để biểu thị 1 ký tự Unicode. VD: mã unicode của ký tự đồng euro là 0x20AC.  Để đặt nó vào biểu thức regex, ta dùng \u20AC.

Regex Engine làm việc như thế nào?

Hiểu dc cách làm việc của regex engine sẽ giúp ta viết regex tốt hơn, dễ dàng hơn. Nó giúp ta hiểu dc tại sao 1 regex hoạt động ko như mong muốn, và giúp tiết kiệm thời gian phải mò mẫm khi viết các regex phức tạp.

Có 2 loại regex engine: text-directed engines, và regex-directed engines. Loại cú pháp regex mà ta đang thảo luận ở đây thuộc loại regex-directed engines. Loại engine này phổ biến hơn bởi nó có 1 số chức năng rất hữu dụng như: lazy quantifiers, backreferences,...

Có thể dễ dàng kiểm tra xem loại cú pháp đang sử dụng thuộc về engine nào qua việc kiểm tra xem lazy quantifiers và backreferences có dc hỗ trợ ko. Hãy thử dùng biểu thức regex regex|regex not vào chuỗi regex not xem sao. Nếu kết quả so khớp là regex, thì engine đang dùng thuộc loại regex-directed. Nêu kết quả là regex not, thì engine thuộc loại text-directed. Tại sao lại thế thì hồi sau sẽ rõ

Trong các VD ở các bài tiếp theo, ta sẽ phân tích cụ thể cách thức làm việc của regex engine, qua đó giúp sử dụng regex hiệu quả nhất và tránh mắc lỗi.

Regex-directed engine luôn trả về kết quả so khớp bên trái nhất

Thậm chí nếu 1 match tốt hơn có thể dc tìm thấy nếu tiếp tục so khớp. Đây là điều cần ghi nhớ. Regex-directed engine luôn bắt đầu so khớp với ký tự đầu tiên của chuỗi.

Hãy lấy 1 VD đơn giản nhất để minh hoạ: ta dùng regex cat vào chuỗi He captured a catfish for his cat. Engine sẽ bắt đầu so khớp dấu hiện đầu tiên trong regex là c với ký tự đầu tiên của chuỗi làH. Ko khớp. Vì vậy nó tiếp tục lần lượt so khớp với ký tự thứ 2 và 3 là e và space. Đều ko khớp. Đến ký tự thứ 4, c đã khớp với c. Xong, giờ engine bắt đầu so khớp dấu hiệu thứ 2 trong regex làa với ký tự thứ 5 của chuỗi là a. Khớp. Nhưng đến dấu hiệu thứ 3 của regex là t thì ko khớp với ký tự thứ 6 của chuỗi là p. Lúc này engine ngộ ra rằng ko thể tìm ra 1 match bắt đầu từ ký tự thứ 4 của chuỗi. Vì vậy, nó bắt đầu lại công việc từ đầu, từ ký tự thứ 5 của chuỗi. Regex c ko khớp vớia. Cứ tiếp tục như vậy cho đến ký tự thứ 15 của chuỗi, regex c đã khớp với c. Engine lần lượt so khớp các dấu hiệu còn lại trong regex với các ký tự tiếp theo trong chuỗi: a khớp a, t khớp t. Và như vậy 1 match đã dc tìm thấy bắt đầu từ ký tự 15. Engine sẽ trả về kết quả và ngừng luôn, ko tiếp tục tìm xem còn match nào tốt hơn ko (VD: cat ở cuối chuỗi).

Lớp ký tự (Character Classes - Character Sets)

Lớp ký tự

Sử dụng lớp ký tự, ta sẽ khiến regex engine chỉ chọn ra 1 ký tự để so khớp. Để sử dụng, ta đặt các ký tự cần so khớp vào 2 dấu [ và ]. VD: để so khớp ký tự a hoặc e, ta dùng [ae]. Như vậy biểu thức gr[ae]y sẽ khớp với gray hoặc grey.

Lớp ký tự chỉ so khớp với 1 ký tự đơn. Như vậy gr[ae]y sẽ ko khớp với graay, graey,v.v… Thứ tự các ký tự trong lớp ko quan trọng. Kết quả trả về luôn giống nhau.

Để xác định 1 vùng ký tự trong lớp ký tự, ta sử dụng dấu - . VD: [0-9] so khớp với 1 chữ số từ 0 – 9. Có thể sử dụng nhiều vùng ký tự hoặc kết hợp vùng ký tự với ký tự đơn. VD: [0-9a-fA-F] so khớp với 1 chữ số hệ 16, ko phân biệt chữ hoa, thường. [0-9a-fxA-FX] so khớp với 1 chữ số hệ 16 hoặc chữ cái X, ko phân biệt chữ hoa, thường. Cũng như trên, thứ tự các vùng ko quan trọng.

Lớp ký tự phủ định

Đặt dấu ^ sau [ trong lớp ký tự sẽ phủ định lớp ký tự đó. Kết quả là lớp ký tự sẽ so khớp với bất kỳ ký tự nào ko nằm trong lớp ký tự đó. Lớp ký tự phủ định có thể so khớp với cả ký tự line break.

Chú ý rằng lớp ký tự phủ định vẫn phải dc so khớp với 1 ký tự. VD: q[^u] ko phải là "q ko theo sau bởi u" mà là "q theo sau bởi 1 ký tự ko phải u". Vì vậy nó sẽ ko so khớp với q trong chuỗi Iraq, và sẽ so khớp với q và space trong chuỗi Iraq is a country.

Metacharacter trong lớp ký tự

Trong lớp ký tự, các ký tự mang ý nghĩa đặc biệt hay metacharacter chỉ bao gồm: ] \ ^ -. Các metacharacter nói ở phần trước khi đặt trong lớp ký tự sẽ chỉ dc coi như ký tự thông thường, và do đó ko cần phải giải phóng. VD: để tìm ký tự * hoặc +, ta dùng [+*].

Để đặt ký tự \ vào trong lớp ký tự với nghĩa thông thường, cần giải phóng nó bằng 1 ký tự \ khác. VD: [\\x] sẽ khơp với ký tự \ hoặc x. Các ký tự ] ^ - nếu muốn dùng theo nghĩa thông thường cũng phải dc giải phóng bằng \ hoặc đặt nó ở vị trí mà nó sẽ ko có ý nghĩa đặc biệt. Ta nên dùng cách thứ 2 để biểu thức regex trông dễ nhìn hơn như sau:

Với ^, đặt nó ở bất kỳ chỗ nào trừ vị trí ngay sau [ . VD: [x^] sẽ khớp với x hoặc ^.

Với ], đặt nó ngay sau [ hoặc [^ . VD: []x] sẽ khớp với ] hoặc x. [^]x] sẽ khớp với bất kỳ ký tự nào ko phải là ] hoặc x.

Với -, đặt nó ngay sau [ hoặc [^ , hoặc ngay trước ]. VD: cả [-x] và [x-] đều so khớp với - hoặc x.

Có thể sử dụng tất cả các ký tự ko in dc trong lớp ký tự giống như dùng chúng ngoài lớp ký tự. VD: [$\u20AC] sẽ khớp với $ hoặc ký tự đồng euro (với giả định cú pháp regex đang dùng hỗ trợ unicode).

JGsoft engine, Perl và PCRE còn hỗ trợ kiểu \Q…\E trong lớp ký tự để giải phóng 1 chuỗi ký tự. VD: [\Q[-]\E] sẽ khớp với [ hoặc - hoặc ].

Cú pháp regex của POSIX lại xử lý \ trong lớp ký tự như 1 ký tự thông thường. Đồng nghĩa với việc ta ko thể dùng \ để giải phóng ] ^ -. Để làm việc này ta chỉ còn cách đặt chúng vào các vị trí như trình bày ở trên. Ngoài ra điều này cũng đồng nghĩa với việc các cú pháp tắt (shorthand, VD: \d) ko còn hiệu lực.

Lớp ký tự viết tắt (Shorthand Character Classes)

\d là dạng tắt của [0-9].

\w dc gọi là "ký tự từ" (word character). Chính xác những ký tự nào dc khớp với nó thay đổi tuỳ theo mỗi loại cú pháp regex. Trong tất cả các loại cú pháp, nó sẽ bao gồm [A-Za-z]. Trong hầu hết các loại cú pháp, nó cũng bao gồm cả dấu _ và chữ số.

\s dc gọi là "ký tự trắng" (whitespace character). Nó khớp với ký tự nào thì cũng tùy thuộc vào từng loại cú pháp. Trong kiểu cú pháp thảo luận ở đây, nó bao gồm [\t]. Nghĩa là \s sẽ khớp vớispace hoặc tab. Trong hầu hết cú pháp , nó cũng bao gồm cả ký tự carriage return hoặc line feed, nghĩa là [\t\r\n]. Một số cú pháp khác lại bao gồm thêm cả các ký tự ko in dc hiếm khi dùng như vertical tab hoặc form feed.

Các lớp ký tự viết tắt có thể dc dùng cả trong lẫn ngoài cặp []. VD: \s\d khớp với 1 ký tự trắng theo sau bởi 1 chữ số. [\s\d] khớp với 1 ký tự đơn là 1 ký tự trắng hoặc 1 chữ số. Khi áp dụng vào chuỗi 1 + 2 = 3, regex thứ 1 sẽ khớp với 2 (space và 2), trong khi regex thứ 2 sẽ khớp với 1. [\da-fA-F] khớp với 1 chữ số hệ 16, giống như [0-9a-fA-F].

Lớp ký tự viết tắt phủ định (Negated Shorthand Character Classes)

\D tương đương [^\d]
\W tương đương [^\w]
\S tương đương [^\s]

Cần thận trọng khi sử dụng dạng viết tắt phủ địng bên trong []. [\D\S] khác với [^\d\s]. Regex thứ 2 sẽ khớp với bất kỳ ký tự nào ko phải là chữ số hoặc ký tự trắng. Còn regex thứ 1 sẽ khớp với bất kỳ ký tự nào ko phải là chữ số hoặc ko phải là ký tự trắng. Và vì chữ số ko phải là ký tự trắng và ký tự trắng ko phải là chữ số cho nên [\D\S] sẽ khớp với bất kỳ ký tự nào, bao gồm cả ký tự trắng và chữ số .

Nhắc lại lớp ký tự (Repeating Character Classes)

Nếu nhắc lại lớp ký tự khi dùng các toán tử nhắc lại ? * + , ta sẽ nhắc lại cả lớp ký tự chứ ko chỉ nhắc lại ký tự mà nó so khớp. VD: regex [0-9]+ sẽ khớp với cả 837 lẫn 222.

Nếu muốn nhắc lại chỉ các ký tự dc so khớp, ta cần dùng tham chiếu ngược (backreferences). ([0-9])\1+ sẽ khớp với 222 chứ ko khớp với 837. Khi áp dùng regex này vào chuỗi 833337, nó sẽ khớp với 3333. Chi tiết hơn thì hồi sau sẽ rõ

Ký tự chấm (Dot)

Ký tự Dot khớp với hầu hết các ký tự

Trong biểu thức regex, dấu . là metacharacter dc sử dụng nhiều nhất, và cũng là ký tự bị sử dụng sai nhiều nhất.

Dấu . khớp với 1 ký tự đơn bất kỳ ngoại trừ ký tự newline. Vì vậy, dấu . tương đương với [^\n](trong UNIX) hoặc [^\r\n] (trong Windows).

Trong Perl, dấu . có thể khớp với cả newline nếu ta dùng chế độ "single-line mode". Để sử dụng chế độ này, ta thêm s vào sau biểu thức regex, VD: m/^regex$/s;

JavaScript và VBScript ko có chế độ nào hỗ trợ Dot so khớp với các ký tự line break. Vì vậy, để so khớp với bất kỳ ký tự nào ta phải dùng [\s\S] thay cho Dot. [\s\S] so khớp với 1 ký tự là ký tự trắng (bao gồm cả các ký tự line break) hoặc ko phải ký tự trắng, nghĩa là nó so khớp với bất kỳ ký tự nào.

Sử dụng Dot 1 cách tiết kiệm

Dấu . là 1 metacharacter đầy uy lực. Nó có thể khớp với bất kỳ ký tự nào, nhưng cũng có thể khớp với ký tự mà ta ko muốn. Những trường hợp như thế có thế rất khó nhận ra.

Hãy lấy 1 VD đơn giản để minh hoạ: giải sử ta muốn tìm 1 chuỗi ngày tháng năm dưới dạng mm/dd/yy, trong đó dấu phân cách ngày tháng năm ta để người dùng tuỳ chọn. Giải pháp nhanh nhất là \d\d.\d\d.\d\d. Trông có vẻ ổn. Nó sẽ khớp 1 chuỗi kiểu như 02/12/03. Vấn đề là 1 chuỗi kiểu như 02512703 cũng dc coi là 1 ngày hợp lệ với regex trên (chấm thứ 1 khớp với 5, chấm thứ 2 khớp với 7).

Giải pháp tốt hơn là: \d\d[- /.]\d\d[- /.]\d\d. Regex này cho phép – hoặc space hoặc . hoặc / làm dấu phân cách ngày tháng năm. Lưu ý rằng dấu . trong lớp ký tự là 1 ký tự thông thường, do đó ko cần phải giải phóng. Nhưng regex này vẫn chưa hoàn hảo, nó sẽ coi 99/99/99 là 1 ngày hợp lệ.

Giải pháp tiếp theo: [0-1]\d[- /.][0-3]\d[- /.]\d\d. Ổn hơn nhưng vẫn chưa hoàn hảo, nó có thể khớp với 19/39/99.

Chất lượng của regex thế nào tuỳ thuộc vào yêu cầu của bạn. VD nếu muốn thẩm định thông tin nhập vào từ người dùng thì regex phải thật hoàn hảo. Còn nếu phân tích 1 file dữ liệu mà bạn đã biết chắc mã nguồn tạo ra file đó theo cách thức như thế nào thì regex có thể ở mức vừa đủ mà thôi.

Sử dụng lớp ký tự phủ định thay cho Dot

Hãy lấy 1 VD để tìm hiểu tại sao. Giả sử ta cần tìm 1 chuỗi bao bởi " ". Nghe có vẻ đơn giản như đang giỡn. Chuỗi này có thể có bao nhiêu ký tự tuỳ thích, do đó ".*" có vẻ ổn. Dấu . khớp với bất kỳ ký tự nào, còn dấu * sẽ cho phép . có thể dc nhắc lại bao nhiêu lần tuỳ thích, kể cả 0 lần. Nếu áp dụng regex này vào chuỗi Put a "string" between double quotes, nó sẽ trả về kết quả đúng như mong đợi: "string". Giờ hãy thử với chuỗi Houston, we have a problem with "string one" and "string two". Please respond. Và kết quả là "string one" and "string two", hỏng zồi. Lý do là vì * vốn có bản tính "tham lam" (greedy). Chi tiết thế nào thì hồi sau sẽ rõ. VD này cho thấy ko nên lạm dụng dấu chấm.

Trong VD tìm ngày ở trên, ta cải tiến regex bằng cách sử dụng lớp ký tự thay cho dấu chấm. Giờ ta cũng làm như vậy. Ta ko muốn có số lượng bất kỳ các ký tự bất kỳ trong cặp dấu " ", mà muốn có số lượng bất kỳ các ký tự ko phải là " hoặc newline trong cặp dấu " ". Do đó regex đúng sẽ là"[^"\r\n]*".

Mỏ neo (anchors)

Neo đầu và cuối chuỗi

Từ đầu đến giờ, ta đã tìm hiểu về các ký tự thông thường và lớp ký tự. Đặt 1 ký tự thông thường hoặc 1 lớp ký tự vào biểu thức regex, ta sẽ bắt regex engine đi so khớp với 1 ký tự đơn.

Mỏ neo thuộc về 1 dạng khác. Chúng ko so khớp với bất kỳ 1 ký tự nào. Thay vào đó, chúng so khớp với 1 vị trí trước, sau hoặc giữa các ký tự. Chúng dc sử dụng để "neo" biểu thức regex vào 1 vị trí để so khớp. Dấu ^ khớp với vị trí ngay trước ký tự đầu tiên trong chuỗi. Áp dụng regex ^a cho chuỗi abc, ta sẽ được a. ^b sẽ ko có kết quả khi so khớp với abc, vì b ko khớp với ký tự ngay sau vị trí bắt đầu của chuỗi, vị trí dc khớp bởi ^.

Tương tự như trên, $ khớp với vị trí ngay sau ký tự cuối cùng của chuỗi. c$ sẽ khớp với c trongabc, trong khi a$ ko khớp.

Thực hành

Khi sử dụng regex trong ngôn ngữ lập trình để kiểm định thông tin nhập vào từ người dùng, sử dụng neo là rất quan trọng. VD nếu ta dùng \d+ để kiểm tra xem người dùng có nhập vào 1 số nguyên hay ko, kết quả trả về vẫn có thể là đúng thậm chí nếu người dùng nhập qsdf4ghjk, bởi\d+ khớp với 4. Regex đúng ở đây phải là ^\d+$. Bởi vì vị trí đầu chuỗi phải dc khớp trước khi \d+dc khớp, và vị trí cuối chuỗi phải dc khớp ngay sau đó, vì vậy chuỗi nhập vào nếu muốn khớp với^\d+$ thì chỉ có thể là 1 chuỗi các chữ số (dấu + là toán tử nhắc lại, dùng để nhắc lại ký tự trước nó 1 hoặc nhiều lần, chi tiết thì hồi sau sẽ rõ )

1 chú ý khác là ta có thể dễ dàng mắc lỗi với ký tự trắng. Trong ngôn ngữ Perl chẳng hạn, khi đọc vào 1 dòng từ 1 file text, ký tự line break cũng sẽ dc lưu vào biến. Do đó trước khi tiến hành kiểm định thông tin nhập vào, ta cần chặt bỏ các ký tự trắng đầu và cuối. ^\s+ khớp với ký tự trắng đầu và \s+$ khớp với ký tự trắng cuối.

Sử dụng ^ và $ để neo đầu và cuối 1 dòng

Nếu chuỗi cần xử lý dc viết trên nhiều dòng, như kiểu first line\nsecond line (\n là ký tự line break), ta có thể muốn làm việc với từng dòng hơn là với cả chuỗi. Do đó, các regex engine dc thảo luận trong loạt bài này còn có thêm chức năng mở rộng ý nghĩa của các mỏ neo. ^ vừa có thể khớp với vị trí đầu chuỗi (trước ký tự f trong VD trên), vừa có thể khớp với vị trí ngay sau mỗi line break (giữa \n và s). Cũng như vậy, $ vừa có thể khớp với vị trí cuối chuỗi (sau ký tự e cuối cùng), vừa có thể khớp với vị trí trước mỗi line break (giữa e và \n).

Trong ngôn ngữ lập trình, ta phải kích hoạt chức năng mở rộng này, dc gọi là chế độ đa dòng (multi-line mode). VD trong Perl, ta làm việc này bằng cách thêm m vào sau đoạn mã regex, VD: m/^regex$/m;

Neo đầu và cuối chuỗi vĩnh cửu

\A sẽ chỉ khớp với vị trí đầu chuỗi, và \Z chỉ khớp với vị trí cuối chuỗi. Chúng ko bao giờ khớp ở vị trí các line break, thậm chí cả khi chế độ "multiline mode" dc kích hoạt. Điều này đúng cho tất cả các loại cú pháp regex dc thảo luận trong loạt bài này.

Match có độ dài 0 (Zero-Length Matches)

Ta đã biết các mỏ neo khớp với 1 vị trí chứ ko phải khớp với 1 ký tự. Điều này cũng có nghĩa là nếu biểu thức regex chỉ bao gồm 1 hoặc nhiều mỏ neo, kết quả so khớp có thể có độ dài 0. Tuỳ vào từng tình huống mà điều này có thể rất hữu dụng hoặc là tai họa. Chẳng hạn ta dử dụng ^\d*$để kiểm tra xem người dùng có nhập vào 1 số hay ko (chú ý ở đây ta dùng * thay cho + trong VD ở trên, * cũng là toán tử nhắc lại, dùng để nhắc lại ký tự trước nó 0 hoặc nhiều lần, chi tiết thì hồi sau sẽ rõ ). Điều này có thể dẫn tới việc chấp nhận 1 chuỗi rỗng là thông tin nhập vào hợp lệ.

Tuy nhiên, chỉ khớp với vị trí cũng có thể rất hữu dụng. VD như trong email, các dòng trong message trích dẫn thường dc bắt đầu bởi dấu > và space. Với chế độ "multi-line mode", ta có thể dùng regex ^ để "tóm" lấy với vị trí đầu của message trích dẫn, và vị trí ngay sau mỗi ký tự newline (đầu mỗi dòng trong message trích dẫn). Nhờ đó, khi sử dụng các hàm hay phương thức của ngôn ngữ lập trình, ta có thể loại bỏ kết quả so khớp (match) và thay thế vào đó chuỗi mà ta muốn (ở đây là chuỗi gồm ký tự > và space). Bởi vì kết quả so khớp ở đây ko chứa ký tự nào cả, cho nên ko có gì bị xoá đi. Nhưng nó chứa vị trí đầu các dòng trong message trích dẫn, do đó chuỗi >space sẽ được đặt vào đúng vị trí đó, điều mà ta muốn. VD trong PHP của chúng ta, đoạn mã này sẽ thêm >space vào đầu chuỗi:

<?php
echo preg_replace('/^/', '> ', 'I love LazyDog');
?>

Chuỗi kết thúc bởi Line Break

Mặc dù $ (khi ko kích hoạt "multi-line mode") và \Z chỉ khớp với vị trí cuối chuỗi, nhưng có 1 ngoại lệ ở đây. Nếu chuỗi dc kết thúc bởi ký tự line break, khi đó \Z và $ sẽ khớp với vị trí ngay trước ký tự line break, thay vì vị trí cuối chuỗi thực sự (sau line break). Tính năng tăng cường này dc đưa ra bởi Perl, và sau đó dc các loại cú pháp khác copy , bao gồm: Java, .NET và PCRE. Trong Perl, khi đọc vào 1 dòng từ file, chuỗi kết quả sẽ dc kết thúc bởi line break. VD khi đọc 1 dòng từ file chứa đoạn text lazydog, kết quả sẽ là lazydog\n. Khi áp dùng regex vào chuỗi này, cả ^[a-z]+$ và\A[a-z]+\Z đều khớp với lazydog.

Nếu muốn khớp với vị trí cuối chuỗi thực sự, ta sử dụng \z. \A[a-z]+\z sẽ ko khớp với lazydog\n. Vì\z khớp với vị trí sau line break, mà line break lại ko dc khớp bởi lớp ký tự [a-z].

Quan sát sự làm việc của Regex Engine

Hãy xem regex engine làm việc như thế nào khi ta khớp biểu thức ^4$ vào chuỗi 749\n486\n4 (\n là ký tự newline) ở chế độ "multi-line mode".

Như bình thường, regex engine bắt đầu với ký tự đầu tiên: 7. Dấu hiệu (token) đầu tiên trong biểu thức regex là ^. Vì dấu hiệu này là dấu hiệu rỗng, nên engine sẽ ko cố khớp nó với 1 ký tự, thay vào đó nó sẽ khớp với 1 vị trí trước ký tự hiện hành. Và ^ dĩ nhiên sẽ khớp dc với vị trí trước 7. Engine sau đó sẽ tiếp tục xử lý dấu hiệu thứ 2 trong regex: 4. Vì dấu hiệu trước đó là rỗng, nên engine sẽ ko nhảy tới ký tự tiếp theo trong chuỗi mà vẫn dừng lại ở 7. 4 là ký tự thông thường, nó ko khớp với 7. Ko có khả năng nào khác ở đây, vì vậy engine phải bắt đầu lại từ đầu với dấu hiệu đầu tiên, và bây giờ xuất phát từ ký tự 4 trong chuỗi. Lần này, ^ ko thể khớp với vị trí trước 4. Vì phía trước vị trí này là 1 ký tự (7), và ký tự đó ko phải là newline. Engine lại làm lại từ đầu, từ ký tự9, và lại thất bại. Lần thử tiếp theo, ở ký tự \n, vẫn thất bại. Vì cũng như trên,  phía trước vị trí trước \n là 1 ký tự (9) và 9 ko phải là newline.

Engine tiếp tục làm lại từ đầu ở ký tự 4 (thứ hai) trong chuỗi. Bây giờ ^ đã có thể khớp với vị trí trước 4, vì trước vị trí này là 1 ký tự newline. Xong dấu hiệu thứ nhất, engine xử lý dấu hiệu thứ 2 của regex, 4, nhưng ko nhảy tới ký tự tiếp theo trong chuỗi. 4 khớp với 4. Giờ engine sẽ nhảy sang dấu hiệu thứ ba của regex và nhảy sang ký tự tiếp theo trong chuỗi. Nó cố gắng khớp $ với vị trí trước (chú ý: vẫn là trước) ký tự 8. $ ko thể khớp ở đây, vì vị trí này bị theo sau bởi 1 ký tự, và ký tự này ko phải là newline.

Engine tiếp tục kiên trì làm lại từ đầu. Lần trước, ^ đã dc khớp ở ký tự 4 (thứ hai), vì vậy lần này engine sẽ bắt đầu lại từ ký tự 8. ^ ko khớp với vị trí trước 8. Và cũng như vậy với ký tự 6 và \n.

Lại làm lại, giờ engine cố khớp ^ ở ký tự 4 (thứ ba) của chuỗi. Trước vị trí trước 4 là ký tự \n(newline). Vậy là thành công. Sau đó, engine tiếp tục khớp thành công 4 với 4. Giờ đến dấu hiệu cuối cùng là $, và ký tự cần so khớp bây giờ chính là 1 cái "ký tự"… chả có gì (void) nằm ở cuối chuỗi. Cứ theo nguyên tắc thì $ sẽ check vị trí phía trước cái "ký tự" này, và vị trí này dc theo sau bởi cái "ký tự" chả có gì đó, vậy là OK zồi . Nghĩa là, $ sẽ check chính cái ký tự hiện hành, nếu nó là ký tự newline hoặc "ký tự"… chả có j (hay đúng hơn là chả còn gì để mà check) thì so khớp sẽ thành công. Như vậy ở đây $ đã so khớp thành công.

Thế là cuối cùng, engine cũng đã tìm ra dc 1 match: đó là ký tự 4 cuối cùng trong chuỗi. Nghe có vẻ rắc rối nhưng thực chất hoạt động của engine hết sức logic và đơn giản.

1 quan sát khác

Ở phần trên ta đã thấy ^\d*$ có thể khớp thành công với 1 chuỗi rỗng. Giờ hãy xem tại sao.

Chỉ có 1 "ký tự" duy nhất trong chuỗi rỗng: ký tự void cuối chuỗi (hay là chả có gì ). Dấu hiệu đầu tiên trong regex là ^. Nó khớp với vị trí trước ký tự void này, vì trước vị trí này là 1 ký tự void khác, ký tự void đầu chuỗi . Dấu hiệu tiếp theo của regex là \d*. Engine sẽ cố khớp \d với ký tự void cuối chuỗi, dĩ nhiên là thất bại. Nhưng nhờ có dấu * (nhắc lại ký tự trước nó 0 hoặc nhiều lần) cho nên lần so khớp này vẫn tìm ra dc 1 match (nhưng có độ dài 0). Engine lại tiếp tục tiến đến dấu hiệu cuối cùng $, và ký tự cần so khớp vẫn giữ nguyên, là ký tự void cuỗi chuỗi. Và như ta đã biết ở trên, so khớp này cũng thành công. Do đó, kết quả so khớp toàn bộ regex là 1 chuỗi rỗng, và engine sẽ thông báo là thành công

Tóm tắt:

1. ^ : đại diện cho kí tự đầu tiên của chuỗi.
^a : tìm kí tự a ở đầu chuỗi.
2. $ : đại diện cho kí tự cuối cùng của chuỗi.
a$ : tìm kí tự a ở cuối chuỗi.
3.\ : Hiển thị kí tự đặc biệt như $, *, . , \
4. . : Dấu chấm đại diện cho kí tự bất kì, kể cả dấu cách.
5. [] : Kí hiệu tập hợp. [abc] : tìm tất cả những phần tử a hoặc b hoặc c có trong chuỗi nguồn.
[ab][cd] = Tìm các chuỗi ac, ad, bc, bd.(Giống như nhân phân phối trong toán học vậy)
6. Nếu muốn tìm 1 chuỗi mà các kí tự của chuỗi là liền nhau thì ta dùng dấu -.
Vd : [0-9] : sẽ tìm các chữ số 0,1,2,3,4,5,6,7,8,9.
[a-z] : tìm tất cả các chữ thường.
7. [^a-z] : Dấu mũ đứng trước 1 tập hợp mang ý nghĩa phủ định tập hợp ấy, trong vd này tức là ta sẽ lấy các kí tự trừ các kí tự thường.
8. () : Đại diện cho tập hợp các mẫu con.
Kí tự | : mang ý nghĩa là "hoặc (or)"
vd : (I|you|we) : Tìm các chuỗi con I hoặc you hoặc we.
9. a* : Dấu * đại diện cho số lần xuất hiện của kí tự đứng trước nó từ 0 – n lần.
a* : <null>, a, aa, aaa, aaaa, ….
10. a+ : Tương tự dấu *, kí tự đứng trước dấu cộng có thể xuất hiện từ 1 – n lần.
a+ : a, aa, aaa, …
11. a? : Kí tự đứng trước dấu hỏi có thể xuất hiện từ 0 – 1 lần. Nói cách khác, dấu hỏi đại diện cho "có hoặc không".
12. {} : Đại diện cho số lần lặp lại kí tự đứng trước.
Vd : a{3} = aaa
a{1,3} = a, aa, aaa.
A{3,} = Kí tự xuất hiện 3 hoặc n lần.
13. \w : Đại diện cho các chữ cái, chữ số và dấu _.
\w = [A-z0-9_]
14. \W : Phủ định của \w
15. \s : Lấy tập hợp các khoảng trắng.
16. \S : Phủ định của \s, lấy tất cả các kí tự, trừ khoảng trắng.
17. \d : Đại diện cho các chữ số.
18. \A : Tương đương với dấu ^.
19. \Z : Tương đương với dấu $.
20. Một số biểu thức quan trọng :
(?=<pattern>) : Lấy những kí tự mà kí tự đứng sau nó = <pattern>
(?!<pattern>) : Lấy những kí tự mà kí tự đứng sau nó khác <pattern>
(?<=<pattern>) : Lấy những kí tự đứng sau <pattern>

Thứ Tư, 21 tháng 11, 2012

Tạo phiếu khảo sát trực tuyến với Google Docs

Google Docs thường được biết đến như bộ công cụ Office miễn phí của Google cho phép người dùng chỉnh sửa, chia sẻ dữ liệu trên nền các ứng dụng văn phòng như Word, Excel và PowerPoint. Tuy nhiên, bài viết này sẽ giới thiệu về một ứng dụng hữu ích khác của Google Docs trong việc thực hiện các khảo sát, điều tra trực tuyến. Để có thể sử dụng được ứng dụng Google Docs, trước hết cần đăng nhập với tài khoản Google theo đường dẫn:http://docs.google.com

Để bắt đầu tạo phiếu điều tra, cần truy cập menu "Create new" sau đó chọn định dạng "Form"
Giao diện tạo câu hỏi mới trong phiếu điều tra:
Các loại câu hỏi cung cấp trong Google Docs/Form
Để thêm câu hỏi mới. chọn "Add new item"
Để tiếp tục soạn thảo/chỉnh sửa câu hỏi mới, di chuột vào câu hỏi đó và chọn vào biểu tượng chỉnh sửa (Edit) có hình cái bút
Trong quá trình soạn thảo câu hỏi, nhớ thường xuyên chọn lệnh "Save" để bảo vệ thành quả của bạn.
Sau khi soạn thảo xong các câu hỏi, đóng cửa sổ soạn thảo để quay trở về giao diện chính của Google Docs. Khi đó, phiếu điều tra của bạn sẽ được hiển thị trong danh mục file.
Khi phiếu điều tra được mở, chọn vào menu "Form" để thực hiện các tác vụ tiếp theo.
Đến đây chúng ta đã hoàn tất việc soạn thảo mẫu phiếu điều tra và gửi link đến khách hàng. Chúc các bạn ứng dụng thành công công cụ này. 
Liên kết quảng cáo :