diff --git a/README.md b/README.md
index 1d03eae..0c5a795 100644
--- a/README.md
+++ b/README.md
@@ -40,6 +40,7 @@ Dump the software license list of Python packages installed with pip.
     * [Verify options](#verify-options)
         * [Option: fail\-on](#option-fail-on)
         * [Option: allow\-only](#option-allow-only)
+        * [Option: partial\-match](#option-partial-match)
     * [More Information](#more-information)
 * [Dockerfile](#dockerfile)
 * [About UnicodeEncodeError](#about-unicodeencodeerror)
@@ -545,6 +546,49 @@ $ echo $?
 1
 ```
 
+#### Option: partial\-match
+
+If set, enables partial (substring) matching for `--fail-on` or `--allow-only`. Default is unset (False).
+
+Usage:
+
+```bash
+(venv) $ pip-licenses --partial-match --allow-only="MIT License;BSD License"
+(venv) $ pip-licenses --partial-match --fail-on="MIT License;BSD License"
+
+```
+
+**Note:** Semantics are the same as with `--fail-on` or `--allow-only`. This only enables substring matching.
+```
+# keyring library has 2 licenses
+$ pip-licenses --package keyring
+ Name     Version  License
+ keyring  23.0.1   MIT License; Python Software Foundation License
+
+# One or both licenses must be specified (order and case does not matter). Following checks will pass:
+$ pip-licenses --package keyring --allow-only="MIT License"
+$ pip-licenses --package keyring --allow-only="mit License"
+$ pip-licenses --package keyring --allow-only="BSD License;MIT License"
+$ pip-licenses --package keyring --allow-only="Python Software Foundation License"
+$ pip-licenses --package keyring --allow-only="Python Software Foundation License;MIT License"
+
+# These won't pass, as they're not a full match against one of the licenses
+$ pip-licenses --package keyring --allow-only="MIT"
+$ echo $?
+1
+$ pip-licenses --package keyring --allow-only="mit"
+$ echo $?
+1
+
+# with --partial-match, they pass
+$ pip-licenses --package keyring --partial-match --allow-only="MIT"
+$ echo $?
+0
+$ pip-licenses --package keyring --partial-match --allow-only="mit"
+$ echo $?
+0
+```
+
 
 ### More Information
 
diff --git a/piplicenses.py b/piplicenses.py
old mode 100644
new mode 100755
index b8def73..65c5779
--- a/piplicenses.py
+++ b/piplicenses.py
@@ -316,9 +316,15 @@ def get_packages(
         )
 
         if fail_on_licenses:
-            failed_licenses = case_insensitive_set_intersect(
-                license_names, fail_on_licenses
-            )
+            failed_licenses = set()
+            if not args.partial_match:
+                failed_licenses = case_insensitive_set_intersect(
+                    license_names, fail_on_licenses
+                )
+            else:
+                failed_licenses = case_insensitive_partial_match_set_intersect(
+                    license_names, fail_on_licenses
+                )
             if failed_licenses:
                 sys.stderr.write(
                     "fail-on license {} was found for package "
@@ -331,9 +337,16 @@ def get_packages(
                 sys.exit(1)
 
         if allow_only_licenses:
-            uncommon_licenses = case_insensitive_set_diff(
-                license_names, allow_only_licenses
-            )
+            uncommon_licenses = set()
+            if not args.partial_match:
+                uncommon_licenses = case_insensitive_set_diff(
+                    license_names, allow_only_licenses
+                )
+            else:
+                uncommon_licenses = case_insensitive_partial_match_set_diff(
+                    license_names, allow_only_licenses
+                )
+
             if len(uncommon_licenses) == len(license_names):
                 sys.stderr.write(
                     "license {} not in allow-only licenses was found"
@@ -409,6 +422,24 @@ def case_insensitive_set_intersect(set_a, set_b):
     return common_items
 
 
+def case_insensitive_partial_match_set_intersect(set_a, set_b):
+    common_items = set()
+    for item_a in set_a:
+        for item_b in set_b:
+            if item_b.lower() in item_a.lower():
+                common_items.add(item_a)
+    return common_items
+
+
+def case_insensitive_partial_match_set_diff(set_a, set_b):
+    uncommon_items = set_a.copy()
+    for item_a in set_a:
+        for item_b in set_b:
+            if item_b.lower() in item_a.lower():
+                uncommon_items.remove(item_a)
+    return uncommon_items
+
+
 def case_insensitive_set_diff(set_a, set_b):
     """Same as set.difference() but case-insensitive"""
     uncommon_items = set()
@@ -761,6 +792,7 @@ class CustomNamespace(argparse.Namespace):
     with_notice_file: bool
     filter_strings: bool
     filter_code_page: str
+    partial_match: bool
     fail_on: Optional[str]
     allow_only: Optional[str]
 
@@ -1055,6 +1087,12 @@ def create_parser() -> CompatibleArgumentParser:
         help="fail (exit with code 1) on the first occurrence "
         "of the licenses not in the semicolon-separated list",
     )
+    verify_options.add_argument(
+        "--partial-match",
+        action="store_true",
+        default=False,
+        help="enables partial matching for --allow-only/--fail-on",
+    )
 
     return parser
 

diff --git a/test_piplicenses.py b/test_piplicenses.py
index 5a704b1..34ff75f 100644
--- a/test_piplicenses.py
+++ b/test_piplicenses.py
@@ -33,6 +33,8 @@ from piplicenses import (
     CompatibleArgumentParser,
     FromArg,
     __pkgname__,
+    case_insensitive_partial_match_set_diff,
+    case_insensitive_partial_match_set_intersect,
     case_insensitive_set_diff,
     case_insensitive_set_intersect,
     create_licenses_table,
@@ -769,6 +771,42 @@ class TestGetLicenses(CommandLineTestCase):
         self.assertTrue({"revised BSD"} == b_intersect_c)
         self.assertTrue(len(a_intersect_empty) == 0)
 
+    def test_case_insensitive_partial_match_set_diff(self) -> None:
+        set_a = {"MIT License"}
+        set_b = {"Mit", "BSD License"}
+        set_c = {"mit license"}
+        a_diff_b = case_insensitive_partial_match_set_diff(set_a, set_b)
+        a_diff_c = case_insensitive_partial_match_set_diff(set_a, set_c)
+        b_diff_c = case_insensitive_partial_match_set_diff(set_b, set_c)
+        a_diff_empty = case_insensitive_partial_match_set_diff(set_a, set())
+
+        self.assertTrue(len(a_diff_b) == 0)
+        self.assertTrue(len(a_diff_c) == 0)
+        self.assertIn("BSD License", b_diff_c)
+        self.assertIn("MIT License", a_diff_empty)
+
+    def test_case_insensitive_partial_match_set_intersect(self) -> None:
+        set_a = {"Revised BSD"}
+        set_b = {"Apache License", "revised BSD"}
+        set_c = {"bsd"}
+        a_intersect_b = case_insensitive_partial_match_set_intersect(
+            set_a, set_b
+        )
+        a_intersect_c = case_insensitive_partial_match_set_intersect(
+            set_a, set_c
+        )
+        b_intersect_c = case_insensitive_partial_match_set_intersect(
+            set_b, set_c
+        )
+        a_intersect_empty = case_insensitive_partial_match_set_intersect(
+            set_a, set()
+        )
+
+        self.assertTrue(set_a == a_intersect_b)
+        self.assertTrue(set_a == a_intersect_c)
+        self.assertTrue({"revised BSD"} == b_intersect_c)
+        self.assertTrue(len(a_intersect_empty) == 0)
+
 
 class MockStdStream(object):
     def __init__(self) -> None:
@@ -850,6 +888,35 @@ def test_allow_only(monkeypatch) -> None:
     )
 
 
+def test_allow_only_partial(monkeypatch) -> None:
+    licenses = (
+        "Bsd",
+        "Apache",
+        "Mozilla Public License 2.0 (MPL 2.0)",
+        "Python Software Foundation License",
+        "Public Domain",
+        "GNU General Public License (GPL)",
+        "GNU Library or Lesser General Public License (LGPL)",
+    )
+    allow_only_args = [
+        "--partial-match",
+        "--allow-only={}".format(";".join(licenses)),
+    ]
+    mocked_stdout = MockStdStream()
+    mocked_stderr = MockStdStream()
+    monkeypatch.setattr(sys.stdout, "write", mocked_stdout.write)
+    monkeypatch.setattr(sys.stderr, "write", mocked_stderr.write)
+    monkeypatch.setattr(sys, "exit", lambda n: None)
+    args = create_parser().parse_args(allow_only_args)
+    create_licenses_table(args)
+
+    assert "" == mocked_stdout.printed
+    assert (
+        "license MIT License not in allow-only licenses was found for "
+        "package" in mocked_stderr.printed
+    )
+
+
 def test_different_python() -> None:
     import tempfile
 
@@ -891,6 +958,27 @@ def test_fail_on(monkeypatch) -> None:
     )
 
 
+def test_fail_on_partial_match(monkeypatch) -> None:
+    licenses = ("MIT",)
+    allow_only_args = [
+        "--partial-match",
+        "--fail-on={}".format(";".join(licenses)),
+    ]
+    mocked_stdout = MockStdStream()
+    mocked_stderr = MockStdStream()
+    monkeypatch.setattr(sys.stdout, "write", mocked_stdout.write)
+    monkeypatch.setattr(sys.stderr, "write", mocked_stderr.write)
+    monkeypatch.setattr(sys, "exit", lambda n: None)
+    args = create_parser().parse_args(allow_only_args)
+    create_licenses_table(args)
+
+    assert "" == mocked_stdout.printed
+    assert (
+        "fail-on license MIT License was found for "
+        "package" in mocked_stderr.printed
+    )
+
+
 def test_enums() -> None:
     class TestEnum(Enum):
         PLAIN = P = auto()

Consider enabling partial matching for licenses
Hello,

there are use cases, where partial matching on license name could be beneficial, such as when one would like to match all versions of a license - say BSD or GPL or  GPLv3 vs GPLv3+.

Consider adding a way to enable partial matching against licenses, as a non-default option, to ease maintenance of long licenses allow/block lists.

Thanks!
test_piplicenses.py::PYCODESTYLE test_piplicenses.py::TestGetLicenses::test_case_insensitive_partial_match_set_diff test_piplicenses.py::TestGetLicenses::test_case_insensitive_partial_match_set_intersect test_piplicenses.py::TestGetLicenses::test_case_insensitive_set_diff test_piplicenses.py::TestGetLicenses::test_case_insensitive_set_intersect test_piplicenses.py::TestGetLicenses::test_display_multiple_license_from_classifier test_piplicenses.py::TestGetLicenses::test_find_license_from_classifier test_piplicenses.py::TestGetLicenses::test_format_confluence test_piplicenses.py::TestGetLicenses::test_format_csv test_piplicenses.py::TestGetLicenses::test_format_json test_piplicenses.py::TestGetLicenses::test_format_json_license_manager test_piplicenses.py::TestGetLicenses::test_format_markdown test_piplicenses.py::TestGetLicenses::test_format_plain test_piplicenses.py::TestGetLicenses::test_format_plain_vertical test_piplicenses.py::TestGetLicenses::test_format_rst_default_filter test_piplicenses.py::TestGetLicenses::test_format_rst_without_filter test_piplicenses.py::TestGetLicenses::test_from_classifier test_piplicenses.py::TestGetLicenses::test_from_meta test_piplicenses.py::TestGetLicenses::test_from_mixed test_piplicenses.py::TestGetLicenses::test_if_no_classifiers_then_no_licences_found test_piplicenses.py::TestGetLicenses::test_ignore_normalized_packages test_piplicenses.py::TestGetLicenses::test_ignore_packages test_piplicenses.py::TestGetLicenses::test_ignore_packages_and_version test_piplicenses.py::TestGetLicenses::test_order_author test_piplicenses.py::TestGetLicenses::test_order_license test_piplicenses.py::TestGetLicenses::test_order_maintainer test_piplicenses.py::TestGetLicenses::test_order_name test_piplicenses.py::TestGetLicenses::test_order_url test_piplicenses.py::TestGetLicenses::test_order_url_no_effect test_piplicenses.py::TestGetLicenses::test_output_colored_bold test_piplicenses.py::TestGetLicenses::test_output_colored_normal test_piplicenses.py::TestGetLicenses::test_select_license_by_source test_piplicenses.py::TestGetLicenses::test_summary test_piplicenses.py::TestGetLicenses::test_summary_sort_by_count test_piplicenses.py::TestGetLicenses::test_summary_sort_by_name test_piplicenses.py::TestGetLicenses::test_summary_warning test_piplicenses.py::TestGetLicenses::test_with_authors test_piplicenses.py::TestGetLicenses::test_with_default_filter test_piplicenses.py::TestGetLicenses::test_with_description test_piplicenses.py::TestGetLicenses::test_with_empty_args test_piplicenses.py::TestGetLicenses::test_with_license_file test_piplicenses.py::TestGetLicenses::test_with_license_file_no_path test_piplicenses.py::TestGetLicenses::test_with_license_file_warning test_piplicenses.py::TestGetLicenses::test_with_maintainers test_piplicenses.py::TestGetLicenses::test_with_normalized_packages test_piplicenses.py::TestGetLicenses::test_with_notice_file test_piplicenses.py::TestGetLicenses::test_with_packages test_piplicenses.py::TestGetLicenses::test_with_packages_with_system test_piplicenses.py::TestGetLicenses::test_with_specified_filter test_piplicenses.py::TestGetLicenses::test_with_system test_piplicenses.py::TestGetLicenses::test_with_urls test_piplicenses.py::TestGetLicenses::test_without_filter test_piplicenses.py::TestGetLicenses::test_without_version test_piplicenses.py::test_output_file_success test_piplicenses.py::test_output_file_error test_piplicenses.py::test_output_file_none test_piplicenses.py::test_allow_only test_piplicenses.py::test_allow_only_partial test_piplicenses.py::test_different_python test_piplicenses.py::test_fail_on test_piplicenses.py::test_fail_on_partial_match test_piplicenses.py::test_enums test_piplicenses.py::test_verify_args test_piplicenses.py::test_normalize_pkg_name test_piplicenses.py::test_extract_homepage_home_page_set test_piplicenses.py::test_extract_homepage_project_url_fallback test_piplicenses.py::test_extract_homepage_project_url_fallback_multiple_parts test_piplicenses.py::test_extract_homepage_empty test_piplicenses.py::test_extract_homepage_project_uprl_fallback_capitalisation